home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / macos / uae069b2.src.cpt.hqx / UAE069ß2.SRC.CPT / uae069fl2.src / compiler.c < prev    next >
C/C++ Source or Header  |  1997-06-13  |  136KB  |  4,561 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * m68k emulation
  5.   *
  6.   * Copyright 1996 Bernd Schmidt
  7.   */
  8.  
  9. #include "sysconfig.h"
  10. #include "sysdeps.h"
  11.  
  12. #include "config.h"
  13. #include "options.h"
  14. #include "gensound.h"
  15. #include "sounddep/sound.h"
  16. #include "events.h"
  17. #include "gui.h"
  18. #include "my_memory.h"
  19. #include "custom.h"
  20. #include "machdep/m68k.h"
  21. #include "readcpu.h"
  22. #include "newcpu.h"
  23. #include "ersatz.h"
  24. #include "blitter.h"
  25. #include "debug.h"
  26. #include "autoconf.h"
  27. #include "compiler.h"
  28.  
  29. #ifdef USE_COMPILER
  30.  
  31. #include <sys/mman.h>
  32.  
  33. char *address_space, *good_address_map;
  34.  
  35. code_execfunc exec_me;
  36. uae_u8 nr_bbs_to_run = 1;
  37. int nr_bbs_start = 40;
  38.  
  39. static int compile_failure;
  40. static int quiet_compile = 1;
  41. int i_want_to_die = 1;
  42. static int n_compiled = 0;
  43. static int n_max_comp = 99999999;
  44. static uaecptr call_only_me = 0;
  45.  
  46. int patched_syscalls = 0;
  47.  
  48. static int count_bits(uae_u16 v)
  49. {
  50.     int bits = 0;
  51.     while (v != 0) {
  52.     if (v & 1)
  53.         bits++;
  54.     v >>= 1;
  55.     }
  56.     return bits;
  57. }
  58.  
  59. static uae_u16 bitswap(uae_u16 v)
  60. {
  61.     uae_u16 newv = 0;
  62.     uae_u16 m1 = 1, m2 = 0x8000;
  63.     int i;
  64.     
  65.     for (i = 0; i < 16; i++) {
  66.     if (v & m1)
  67.         newv |= m2;
  68.     m2 >>= 1;
  69.     m1 <<= 1;
  70.     }
  71.     return newv;
  72. }
  73.  
  74. static long long compiled_hits = 0;
  75.  
  76. /* 16K areas with 512 byte blocks */
  77. #define SUBUNIT_ORDER 9
  78. #define PAGE_SUBUNIT (1 << SUBUNIT_ORDER)
  79. #define PAGE_ALLOC_UNIT (PAGE_SUBUNIT * 32)
  80.  
  81. static int zerofd;
  82. static int zeroff;
  83. static struct code_page *first_code_page;
  84.  
  85. static struct code_page *new_code_page(void)
  86. {
  87.     struct code_page *ncp;
  88.     
  89.     ncp = (struct code_page *)mmap(NULL, PAGE_ALLOC_UNIT, 
  90.                    PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE,
  91.                    zerofd, zeroff);
  92.     zeroff += PAGE_ALLOC_UNIT;
  93.     if (ncp) {
  94.     ncp->next = first_code_page;
  95.     first_code_page = ncp;
  96.     ncp->allocmask = 1; /* what a waste */
  97.     }
  98.     return ncp;
  99. }
  100.  
  101. #define NUM_HASH 32768 /* larger values cause some paging on my 16MB machine */
  102. #define HASH_MASK (NUM_HASH-1)
  103. #define MAX_UNUSED_HASH 512
  104.  
  105. static int SCAN_MARK = 1; /* Number of calls after which to scan a function */
  106. static int COMPILE_MARK = 5; /* Number of calls after which to compile a function */
  107.  
  108. /* The main address -> function lookup hashtable. We use the lower bits of
  109.  * the address as hash function. */
  110. static struct hash_entry cpu_hash[NUM_HASH];
  111. /* These aren't really LRU lists... They used to be, but keeping them in that
  112.  * order is costly. The hash LRU list is now a two-part list: Functions that have
  113.  * no code allocated for them are placed at the beginning. Such entries can be
  114.  * recycled when we need a new hash entry. */
  115. static struct hash_block lru_first_block;
  116. static struct hash_entry lru_first_hash;
  117. static struct hash_entry *freelist_hash;
  118. static struct hash_block *freelist_block;
  119. static int num_unused_hash;
  120.  
  121. static int m68k_scan_func(struct hash_entry *);
  122. static int m68k_compile_block(struct hash_block *);
  123.  
  124. static char *alloc_code(struct hash_block *hb, int ninsns)
  125. {
  126.     struct code_page *cp;
  127.     long int allocsize = (ninsns * 32 + PAGE_SUBUNIT-1) & ~(PAGE_SUBUNIT-1);
  128.     uae_u32 allocmask;
  129.     int allocbits;
  130.     int j;
  131.     int last_bit;
  132.  
  133.     if (allocsize >= (PAGE_ALLOC_UNIT - (1 << SUBUNIT_ORDER)))
  134.     return NULL;
  135.     allocbits = (allocsize >> SUBUNIT_ORDER);
  136.     allocmask = (1 << allocbits) - 1;
  137.     
  138.     for (cp = first_code_page; cp != NULL; cp = cp->next) {
  139.     uae_u32 thispage_alloc = cp->allocmask;
  140.     for (j = 1; j < (33 - allocbits); j++) {
  141.         if ((cp->allocmask & (allocmask << j)) == 0) {
  142.         goto found_page;
  143.         }
  144.     }
  145.     }
  146.  
  147.     /* Nothing large enough free: make a new page */
  148.     cp = new_code_page();
  149.     if (cp == NULL)
  150.     return NULL;
  151.     j = 1;
  152.     
  153. found_page:
  154.     /* See whether there is in fact more space for us. If so, allocate all of
  155.      * it. compile_block() will free everything it didn't need. */
  156.  
  157.     allocmask <<= j;
  158.     last_bit = allocbits + j;
  159.     while (last_bit < 32 && (cp->allocmask & (1 << last_bit)) == 0) {
  160.     allocmask |= 1 << last_bit;
  161.     allocsize += PAGE_SUBUNIT;
  162.     last_bit++;
  163.     }
  164.  
  165.     hb->page_allocmask = allocmask;
  166.     hb->cpage = cp;
  167.     cp->allocmask |= allocmask;
  168.     hb->compile_start = ((char *)cp + (j << SUBUNIT_ORDER));
  169.     hb->alloclen = allocsize;
  170.     return hb->compile_start;
  171. }
  172.  
  173. static void remove_hash_from_lists(struct hash_entry *h)
  174. {
  175.     h->lru_next->lru_prev = h->lru_prev;
  176.     h->lru_prev->lru_next = h->lru_next;
  177.     
  178.     h->next->prev = h->prev;
  179.     h->prev->next = h->next;
  180. }
  181.  
  182. static void lru_touch(struct hash_entry *h)
  183. {
  184.     h->lru_next->lru_prev = h->lru_prev;
  185.     h->lru_prev->lru_next = h->lru_next;
  186.     
  187.     h->lru_next = &lru_first_hash;
  188.     h->lru_prev = lru_first_hash.lru_prev;
  189.     h->lru_prev->lru_next = h;
  190.     lru_first_hash.lru_prev = h;
  191. }
  192.  
  193. static void lru_untouch(struct hash_entry *h)
  194. {
  195.     h->lru_next->lru_prev = h->lru_prev;
  196.     h->lru_prev->lru_next = h->lru_next;
  197.     
  198.     h->lru_prev = &lru_first_hash;
  199.     h->lru_next = lru_first_hash.lru_next;
  200.     h->lru_next->lru_prev = h;
  201.     lru_first_hash.lru_next = h;
  202. }
  203.  
  204. static void forget_block(struct hash_block *hb)
  205. {
  206.     struct hash_entry *h = hb->he_first;
  207.     
  208.     hb->lru_next->lru_prev = hb->lru_prev;
  209.     hb->lru_prev->lru_next = hb->lru_next;
  210.  
  211.     hb->lru_next = freelist_block;
  212.     freelist_block = hb;
  213.  
  214.     if (hb->cpage != NULL)
  215.     fprintf(stderr, "Discarding block with code. Tsk.\n");
  216.  
  217.     do {
  218.     struct hash_entry *next = h->next_same_block;
  219.     h->block = NULL;
  220.     h->execute = NULL;
  221.     h->next_same_block = NULL;
  222.     h = next;
  223.     num_unused_hash++;
  224.     lru_untouch(h);
  225.     } while (h != hb->he_first);
  226.     compiler_flush_jsr_stack();
  227. }
  228.  
  229. static void lru_touch_block(struct hash_block *h)
  230. {
  231.     h->lru_next->lru_prev = h->lru_prev;
  232.     h->lru_prev->lru_next = h->lru_next;
  233.     
  234.     h->lru_next = &lru_first_block;
  235.     h->lru_prev = lru_first_block.lru_prev;
  236.     h->lru_prev->lru_next = h;
  237.     lru_first_block.lru_prev = h;    
  238. }
  239.  
  240. static __inline__ int check_block(struct hash_block *hb)
  241. {
  242. #ifndef RELY_ON_LOADSEG_DETECTION
  243.     struct hash_entry *h = hb->he_first;
  244.     
  245.     do {
  246.     struct hash_entry *next = h->next_same_block;
  247.     if (h->matchword != *(uae_u32 *)get_real_address(h->addr))
  248.         return 0;
  249.     h = next;
  250.     } while (h != hb->he_first);
  251. #endif
  252.     return 1;
  253. }
  254.  
  255. uae_u32 flush_icache(void)
  256. {
  257.     struct hash_block *hb = lru_first_block.lru_next;
  258.     
  259.     while (hb != &lru_first_block) {
  260.     struct hash_block *next = hb->lru_next;
  261.     if (hb->cpage != NULL) {
  262.         /* Address in chipmem? Then forget about block*/
  263.         if ((hb->he_first->addr & ~0xF80000) != 0xF80000) {
  264.         hb->cpage->allocmask &= ~hb->page_allocmask;
  265.         hb->cpage = NULL;
  266.         forget_block(hb);
  267.         }
  268.     }
  269.     hb = next;
  270.     }
  271.     return m68k_dreg(regs, 0);
  272. }
  273.  
  274. void possible_loadseg(void)
  275. {
  276.     fprintf(stderr, "Possible LoadSeg() detected\n");
  277.     flush_icache();
  278. }
  279.  
  280. static struct hash_block *new_block(void)
  281. {
  282.     struct hash_block *b = freelist_block;
  283.     
  284.     if (b != NULL) {
  285.     freelist_block = b->lru_next;
  286.     } else
  287.     b = (struct hash_block *)malloc(sizeof *b);
  288.     b->nrefs = 0;
  289.     b->cpage = NULL;
  290.     b->he_first = NULL;
  291.     b->translated = b->untranslatable = b->allocfailed = 0;
  292.     return b;
  293. }
  294.  
  295. static struct hash_entry *get_free_hash(void)
  296. {
  297.     struct hash_entry *h;
  298.  
  299.     for (;;) {
  300.     h = freelist_hash;
  301.     if (h != NULL) {
  302.         freelist_hash = h->next_same_block;
  303.         break;
  304.     }
  305.     h = lru_first_hash.lru_next;
  306.     if (num_unused_hash >= MAX_UNUSED_HASH && h->block == NULL
  307.         && !h->locked) 
  308.     {
  309.         remove_hash_from_lists(h);
  310.         num_unused_hash--;
  311.         break;
  312.     }
  313.     h = (struct hash_entry *)malloc(sizeof(struct hash_entry));
  314.     h->next_same_block = NULL;
  315.     h->addr = -1;
  316.     break;
  317.     }
  318.     num_unused_hash++;
  319.     h->block = NULL;
  320.     h->ncalls = 0;
  321.     h->locked = h->cacheflush = 0;
  322.     h->execute = NULL;
  323.     return h;
  324. }
  325.  
  326. static struct hash_entry *new_hash(uaecptr addr)
  327. {
  328.     struct hash_entry *h = get_free_hash();
  329.     
  330.     h->addr = addr;
  331.  
  332.     /* Chain the new node */
  333.     h->prev = cpu_hash + ((addr >> 1) & HASH_MASK);
  334.     h->next = h->prev->next;
  335.     h->next->prev = h->prev->next = h;
  336.  
  337.     h->lru_next = &lru_first_hash;
  338.     h->lru_prev = lru_first_hash.lru_prev;
  339.     h->lru_prev->lru_next = h;
  340.     lru_first_hash.lru_prev = h;
  341.     
  342.     h->next_same_block = NULL;
  343.  
  344.     return h;
  345. }
  346. static struct hash_entry *find_hash(uaecptr addr)
  347. {
  348.     struct hash_entry *h;
  349.     struct hash_entry *h1 = cpu_hash + ((addr >> 1) & HASH_MASK);
  350.  
  351.     if (h1->next->addr == addr)
  352.     return h1->next;
  353.     
  354.     for (h = h1->next; h != h1; h = h->next) {
  355.     if (h->addr == addr) {
  356.         /* Put it at the head of the list so that the above shortcut
  357.          * works the next time we come here */
  358.         h->next->prev = h->prev; h->prev->next = h->next;
  359.         h->prev = h1;
  360.         h->next = h1->next;
  361.         h->next->prev = h->prev->next = h;
  362.         return h;
  363.     }
  364.     }
  365.     return NULL;
  366. }
  367.  
  368. static struct hash_entry *get_hash_for_func(uaecptr addr, int mark_locked)
  369. {
  370.     struct hash_entry *h = find_hash(addr);
  371.     if (h == NULL)
  372.     h = new_hash (addr);
  373. #if 0 /* Too expensive */
  374.     else
  375.     lru_touch(h);
  376. #endif
  377.     if (mark_locked)
  378.     h->locked = 1;
  379.     return h;
  380. }
  381.  
  382. static struct hash_entry *get_hash(uaecptr addr)
  383. {
  384.     struct hash_entry *h = get_hash_for_func(addr, 0);
  385.  
  386.     if (h->block == NULL) {
  387.     if (++h->ncalls == SCAN_MARK) {
  388.         m68k_scan_func(h);
  389.     }
  390.     } else
  391.     if (!h->block->untranslatable && h->block->nrefs++ == COMPILE_MARK) {
  392.         lru_touch_block(h->block);
  393.         if (m68k_compile_block(h->block)) {
  394.         h->block->untranslatable = 1;
  395.         } else {
  396.         h->block->translated = 1;
  397.         }
  398.     }
  399.     return h;
  400. }
  401.  
  402. void special_flush_hash(uaecptr addr)
  403. {
  404.     struct hash_entry *h = get_hash_for_func(addr, 0);
  405.     
  406.     h->cacheflush = 1;
  407. }
  408.  
  409. static __inline__ void m68k_setpc_hash(uaecptr newpc)
  410. {
  411.     struct hash_entry *h = get_hash(newpc);
  412.     
  413.     if (h->cacheflush)
  414.     flush_icache();
  415.  
  416.     if (h->execute != NULL) {
  417.     if ((h->addr & 0xF80000) == 0xF80000 || check_block(h->block)) {
  418.         compiled_hits++;
  419.         if (i_want_to_die && (call_only_me == 0 || call_only_me == newpc)) {
  420.         exec_me = h->execute;
  421.         nr_bbs_to_run = nr_bbs_start;
  422.         regs.spcflags |= SPCFLAG_EXEC;
  423.         }
  424.     } else 
  425.         flush_icache();
  426.     }
  427.     regs.pc = newpc;
  428.     regs.pc_p = regs.pc_oldp = get_real_address(newpc);
  429. }
  430.  
  431. static __inline__ void m68k_setpc_nohash(uaecptr newpc)
  432. {
  433. #if 0
  434.     /* This is probably not too good for efficiency... FIXME */
  435.     struct hash_entry *h = find_hash(newpc);
  436.  
  437.     if (h != NULL && h->cacheflush)
  438.     flush_icache();
  439. #endif
  440.     regs.pc = newpc;
  441.     regs.pc_p = regs.pc_oldp = get_real_address(newpc);
  442. }
  443.  
  444. void m68k_setpc(uaecptr newpc)
  445. {
  446.     m68k_setpc_hash(newpc);    
  447. }
  448.  
  449. void m68k_setpc_fast(uaecptr newpc)
  450. {
  451.     m68k_setpc_nohash(newpc);    
  452. }
  453.  
  454. void m68k_setpc_rte(uaecptr newpc)
  455. {
  456.     m68k_setpc_nohash(newpc);
  457. }
  458.  
  459. void m68k_setpc_bcc(uaecptr newpc)
  460. {
  461.     m68k_setpc_hash(newpc);
  462. }
  463.  
  464. static void hash_init(void)
  465. {
  466.     int i;
  467.     struct hash_entry **hepp;
  468.     
  469.     freelist_block = NULL;
  470.     freelist_hash = NULL;
  471.  
  472.     for(i = 0; i < NUM_HASH; i++) {
  473.     cpu_hash[i].next = cpu_hash[i].prev = cpu_hash + i;
  474.     cpu_hash[i].lru_next = cpu_hash[i].lru_prev = NULL;
  475.     cpu_hash[i].block = NULL;
  476.     cpu_hash[i].locked = 0; cpu_hash[i].cacheflush = 0;
  477.     cpu_hash[i].addr = -1;
  478.     }
  479.  
  480.     lru_first_hash.lru_next = lru_first_hash.lru_prev = &lru_first_hash;
  481.     lru_first_block.lru_next = lru_first_block.lru_prev = &lru_first_block;
  482.  
  483.     num_unused_hash = 0;
  484. }
  485.  
  486. static void code_init(void)
  487. {
  488.     first_code_page = NULL;
  489.     zerofd = open("/dev/zero", O_RDWR);
  490.     zeroff = 0;
  491. }
  492.  
  493. #define CC68K_C 16
  494. #define CC68K_V 8
  495. #define CC68K_Z 4
  496. #define CC68K_N 2
  497. #define CC68K_X 1
  498.  
  499. static __inline__ int cc_flagmask_68k(const int cc)
  500. {
  501.     switch(cc){
  502.      case 0: return 0;                       /* T */
  503.      case 1: return 0;                       /* F */
  504.      case 2: return CC68K_C|CC68K_Z;         /* HI */
  505.      case 3: return CC68K_C|CC68K_Z;         /* LS */
  506.      case 4: return CC68K_C;                 /* CC */
  507.      case 5: return CC68K_C;                 /* CS */
  508.      case 6: return CC68K_Z;                 /* NE */
  509.      case 7: return CC68K_Z;                 /* EQ */
  510.      case 8: return CC68K_V;                 /* VC */
  511.      case 9: return CC68K_V;                 /* VS */
  512.      case 10:return CC68K_N;                 /* PL */
  513.      case 11:return CC68K_N;                 /* MI */
  514.      case 12:return CC68K_N|CC68K_V;         /* GE */
  515.      case 13:return CC68K_N|CC68K_V;         /* LT */
  516.      case 14:return CC68K_N|CC68K_V|CC68K_Z; /* GT */
  517.      case 15:return CC68K_N|CC68K_V|CC68K_Z; /* LE */
  518.     }
  519.     abort();
  520.     return 0;    
  521. }
  522.  
  523. static __inline__ void translate_step_over_ea(uae_u8 **pcpp, amodes m, 
  524.                           wordsizes size)
  525. {
  526.     switch (m) {
  527.      case Areg:
  528.      case Dreg:
  529.      case Aind:
  530.      case Aipi:
  531.      case Apdi:
  532.      case immi:
  533.     break;
  534.  
  535.      case imm:
  536.     if (size == sz_long)
  537.         goto is_long;
  538.     /* fall through */
  539.      case Ad16:
  540.      case PC16:
  541.      case imm0:
  542.      case imm1:
  543.      case absw:
  544.     (*pcpp)+=2;
  545.     break;
  546.      case Ad8r:
  547.      case PC8r:
  548.     {
  549.         uae_u16 extra = *(*pcpp)++;
  550.         extra <<= 8;
  551.         extra |= *(*pcpp)++;
  552.         /* @@@ handle 68020 stuff here */
  553.     }
  554.     break;
  555.      case absl:
  556.      case imm2:
  557.     is_long:
  558.     (*pcpp) += 4;
  559.     break;
  560.     }
  561. }
  562.  
  563. static struct instr *translate_getnextinsn(uae_u8 **pcpp)
  564. {
  565.     uae_u16 opcode;
  566.     struct instr *dp;
  567.     
  568.     opcode = *(*pcpp)++ << 8;
  569.     opcode |= *(*pcpp)++;
  570.     
  571.     if (cpufunctbl[opcode] == op_illg) {
  572.     opcode = 0x4AFC;
  573.     }
  574.     dp = table68k + opcode;
  575.     if (dp->suse) {
  576.     translate_step_over_ea(pcpp, dp->smode, dp->size);
  577.     }
  578.     if (dp->duse) {
  579.     translate_step_over_ea(pcpp, dp->dmode, dp->size);
  580.     }
  581.     return dp;
  582. }
  583.  
  584. #define CB_STACKSIZE 200
  585. #define BB_STACKSIZE 200
  586.  
  587. static uae_u32 condbranch_stack[CB_STACKSIZE];
  588. static int condbranch_src_stack[CB_STACKSIZE];
  589.  
  590. struct bb_info {
  591.     struct hash_entry *h;
  592.     uaecptr stopaddr;
  593.     int can_compile_last;
  594.     struct bb_info *bb_next1, *bb_next2;
  595.     int flags_live_at_end;
  596.     int flags_live_at_start;
  597.     int first_iip, last_iip;
  598. } bb_stack[BB_STACKSIZE];
  599.  
  600. static int top_bb;
  601.  
  602. static uaecptr bcc_target_stack[BB_STACKSIZE];
  603.  
  604. static int new_bcc_target(uaecptr addr)
  605. {
  606.     int i;
  607.     
  608.     for (i = 0; i < top_bb; i++)
  609.     if (bcc_target_stack[i] == addr)
  610.         return 1;
  611.  
  612.     if (top_bb == BB_STACKSIZE)
  613.     return 0;
  614.     bcc_target_stack[top_bb++] = addr;
  615.     return 1;
  616. }
  617.  
  618. static int bcc_compfn(const void *a, const void *b)
  619. {
  620.     uaecptr *a1 = (uaecptr *)a, *b1 = (uaecptr *)b;
  621.     
  622.     if (*a1 == *b1)
  623.     printf("BUG!!\n");
  624.     
  625.     if (*a1 < *b1)
  626.     return 1;
  627.     return -1;
  628. }
  629.  
  630. static int bb_compfn(const void *a, const void *b)
  631. {
  632.     struct bb_info *a1 = (struct bb_info *)a, *b1 = (struct bb_info *)b;
  633.     
  634.     if (a1->h->addr == b1->h->addr)
  635.     printf("BUG!!\n");
  636.     
  637.     if (a1->h->addr < b1->h->addr)
  638.     return -1;
  639.     return 1;
  640. }
  641.  
  642. static int find_basic_blocks(struct hash_entry *h)
  643. {
  644.     int current_bb = 0;
  645.  
  646.     top_bb = 0;
  647.     bcc_target_stack[0] = h->addr;
  648.     new_bcc_target(h->addr);
  649.  
  650.     while (top_bb > current_bb) {
  651.     uaecptr addr = bcc_target_stack[current_bb];
  652.     int ninsns = 0;
  653.     uae_u8 *realpc = get_real_address(addr);
  654.     uae_u8 *rpc_start = realpc;
  655.     
  656.     for(;;) {
  657.         uaecptr thisinsn_addr = (realpc - rpc_start) + addr;
  658.         uae_u8 *rpc_save = realpc;
  659.         struct instr *dp = translate_getnextinsn(&realpc);
  660.         uaecptr nextinsn_addr = (realpc - rpc_start) + addr;
  661.  
  662.         if (dp->mnemo == i_RTS || dp->mnemo == i_RTE 
  663.         || dp->mnemo == i_RTR || dp->mnemo == i_RTD
  664.         || dp->mnemo == i_JMP || dp->mnemo == i_ILLG) 
  665.         {
  666.         break;
  667.         }
  668.         
  669.         if (dp->mnemo == i_BSR || dp->mnemo == i_JSR) {
  670.         if (!new_bcc_target(nextinsn_addr))
  671.             return 0;
  672.         break;
  673.         }
  674.  
  675.         if (dp->mnemo == i_DBcc) {
  676.         uaecptr newaddr = thisinsn_addr + 2 + (uae_s16)((*(rpc_save+2) << 8) | *(rpc_save+3));
  677.         if (!new_bcc_target(nextinsn_addr))
  678.             return 0;
  679.         if (!new_bcc_target(newaddr))
  680.             return 0;
  681.         break;
  682.         }
  683.         
  684.         if (dp->mnemo == i_Bcc) {
  685.         uaecptr newaddr;
  686.         if (dp->smode == imm1)
  687.             newaddr = thisinsn_addr + 2 + (uae_s16)((*(rpc_save+2) << 8) | *(rpc_save+3));
  688.         else
  689.             newaddr = thisinsn_addr + 2 + (uae_s8)dp->sreg;
  690.         
  691.         if (dp->cc != 0)
  692.             if (!new_bcc_target(nextinsn_addr))
  693.             return 0;
  694.         if (!new_bcc_target(newaddr))
  695.             return 0;
  696.         break;
  697.         }
  698.     }
  699.     current_bb++;
  700.     }
  701.  
  702.     qsort(bcc_target_stack, top_bb, sizeof (uaecptr), bcc_compfn);
  703.  
  704.     return 1;
  705. }
  706.  
  707. static int m68k_scan_func(struct hash_entry *h)
  708. {
  709.     int i;
  710.     struct hash_block *found_block;
  711.     struct hash_entry **hepp;
  712.     
  713.     if (!find_basic_blocks(h))
  714.     return 0;
  715.  
  716.     found_block = NULL;
  717.     
  718.     /* First, lock the hash entries we already have to prevent grief */
  719.     for (i = 0; i < top_bb; i++) {
  720.     struct hash_entry *h = find_hash(bcc_target_stack[i]);
  721.     if (h != NULL)
  722.         h->locked = 1;
  723.     }
  724.     
  725.     /* Allocate new ones */
  726.     for (i = 0; i < top_bb; i++) {
  727.     struct hash_entry *h = get_hash_for_func(bcc_target_stack[i], 1);
  728.     bb_stack[i].h = h;
  729. #if 0 /* This doesn't work in all cases */
  730.     if (h->block != NULL && h->block != found_block) {
  731.         if (found_block == NULL) {
  732.         if (h->block->cpage != NULL)
  733.             fprintf(stderr, "Found compiled code\n");
  734.         else
  735.             found_block = h->block;
  736.         } else {
  737.         fprintf(stderr, "Multiple blocks found.\n");
  738.         if (h->block->cpage == NULL)
  739.             forget_block(h->block);
  740.         else if (found_block->cpage == NULL) {
  741.             forget_block(found_block);
  742.             found_block = h->block;
  743.         } else
  744.             fprintf(stderr, "Bad case.\n");
  745.         }
  746.     }
  747. #endif
  748.     }
  749.     if (found_block == NULL) {
  750.     found_block = new_block();
  751.  
  752.     found_block->lru_next = &lru_first_block;
  753.     found_block->lru_prev = lru_first_block.lru_prev;
  754.     found_block->lru_prev->lru_next = found_block;
  755.     lru_first_block.lru_prev = found_block;
  756.     }
  757.  
  758.     hepp = &found_block->he_first;
  759.     found_block->he_first = NULL;
  760.     for (i = 0; i < top_bb; i++) {
  761.     struct bb_info *bb = bb_stack + i;
  762.  
  763.     if (bb->h->block == NULL) {
  764.         num_unused_hash--;
  765.         lru_touch(bb->h);
  766.         bb->h->block = found_block;
  767.         *hepp = bb->h;
  768.         hepp = &bb->h->next_same_block;
  769.     }
  770.     }
  771.     *hepp = found_block->he_first;
  772.     return 1;
  773. }
  774.  
  775. struct ea_reg_info {
  776.     enum { eat_reg, eat_imem, eat_amem, eat_const } ea_type;
  777.     int regs_set:16;
  778.     int regs_used:16;
  779.     int nr_scratch;
  780.     uae_u32 temp1, temp2;
  781. };
  782.  
  783. #define MAX_TRANSLATE 2048
  784. struct insn_info_struct {
  785.     uaecptr address;
  786.     struct instr *dp;
  787.     int flags_set;
  788.     int flags_used;
  789.     int flags_live_at_end;
  790.     int jump_target;
  791.     int jumps_to;
  792.     char *compiled_jumpaddr; /* Address to use for jumps to this insn */
  793.     char *compiled_fillin;   /* Address where to put offset if this is a Bcc */
  794.     int regs_set:16;
  795.     int regs_used:16;
  796.     int stop_translation:2;
  797.     int sync_cache:1;
  798.     int sync_flags:1;
  799.     int ccuser_follows:1;
  800. } insn_info [MAX_TRANSLATE];
  801.  
  802. #define EA_NONE 0
  803. #define EA_LOAD 1
  804. #define EA_STORE 2
  805. #define EA_MODIFY 4
  806.  
  807. #if 0
  808. static void analyze_ea_for_insn(amodes mode, int reg, wordsizes size,
  809.                 struct ea_reg_info *eai,
  810.                 uae_u8 **pcpp, uaecptr pca,
  811.                 int ea_purpose)
  812. {
  813.     uae_u8 *p = *pcpp;
  814.  
  815.     switch(mode) {
  816.      case Dreg:
  817.     eai->ea_type = eat_reg;
  818.     if (size != sz_long && (ea_purpose & EA_STORE))
  819.         ea_purpose |= EA_LOAD;
  820.     if (ea_purpose & EA_LOAD)
  821.         eai->regs_used |= 1 << reg;
  822.     if (ea_purpose & EA_STORE)
  823.         eai->regs_set |= 1 << reg;
  824.     break;
  825.     
  826.      case Areg:
  827.     eai->ea_type = eat_reg;
  828.     if (size != sz_long && (ea_purpose & EA_STORE))
  829.         printf("Areg != long\n");
  830.     if (ea_purpose & EA_LOAD)
  831.         eai->regs_used |= 1 << (8+reg);
  832.     if (ea_purpose & EA_STORE)
  833.         eai->regs_set |= 1 << (8+reg);
  834.     break;
  835.     
  836.      case Ad16:
  837.      case Aind:
  838.      case Apdi:
  839.      case Aipi:
  840.     eai->ea_type = eat_imem;
  841.     eai->regs_used |= 1 << (8+reg);
  842.     break;
  843.  
  844.      case Ad8r:
  845.     eai->ea_type = eat_imem;
  846.     pii->regs_used |= 1 << (8+reg);
  847.  
  848.     eai->temp = (uae_u16)((*p << 8) | *(p+1));
  849.     r = (eai->temp & 0x7000) >> 12;
  850.     (*pcpp) += 2; p += 2;    
  851.     
  852.     if (eai->temp1 & 0x8000)
  853.         pii->regs_used |= 1 << (8+r);
  854.     else
  855.         pii->regs_used |= 1 << r;
  856.     break;
  857.  
  858.      case PC8r:
  859.     eai->ea_type = eat_imem;
  860.     eai->temp1 = (uae_u16)do_get_mem_word((uae_u16 *)p);
  861.     eai->temp2 = pca + (uae_s8)eai->temp1;
  862.     (*pcpp) += 2; p += 2;
  863.     r = (eai->temp1 & 0x7000) >> 12;
  864.  
  865.     if (eai->temp1 & 0x8000)
  866.         pii->regs_used |= 1 << (8+r);
  867.     else
  868.         pii->regs_used |= 1 << r;
  869.     break;
  870.     
  871.      case PC16:    
  872.     eai->ea_type = eat_amem;
  873.     eai->temp1 = pca + (uae_s16)do_get_mem_word((uae_u16 *)p);
  874.     (*pcpp) += 2;
  875.     break;
  876.     
  877.      case absw:
  878.     eai->ea_type = eat_amem;
  879.     eai->temp1 = (uae_s16)do_get_mem_word((uae_u16 *)p);
  880.     (*pcpp) += 2;
  881.     break;
  882.  
  883.      case absl:
  884.     eai->ea_type = eat_amem;
  885.     eai->temp1 = (uae_s32)do_get_mem_long((uae_u32 *)p);
  886.     (*pcpp) += 4;
  887.     break;
  888.  
  889.      case imm:
  890.     if (size == sz_long)
  891.         goto imm2_const;
  892.     if (size == sz_word)
  893.         goto imm1_const;
  894.     
  895.     /* fall through */
  896.      case imm0:
  897.     eai->ea_type = eat_imm;
  898.     eai->temp1 = (uae_s8)*(p+1);
  899.     (*pcpp) += 2;
  900.     break;
  901.  
  902.      case imm1:
  903.     imm1_const:
  904.     eai->ea_type = eat_imm;
  905.     eai->temp1 = (uae_s16)do_get_mem_word((uae_u16 *)p);
  906.     (*pcpp) += 2;
  907.     break;
  908.  
  909.      case imm2:
  910.     imm2_const:
  911.     eai->ea_type = eat_imm;
  912.     eai->temp1 = (uae_s32)do_get_mem_long((uae_u32 *)p);
  913.     (*pcpp) += 4;
  914.     break;
  915.  
  916.      case immi:
  917.     eai->ea_type = eat_imm;
  918.     eai->temp1 = (uae_s8)reg;
  919.     break;
  920.  
  921.      default:
  922.     break;
  923.     }
  924. }
  925. #endif
  926. static struct bb_info *find_bb(struct hash_entry *h)
  927. {
  928.     int i;
  929.     
  930.     if (h == NULL)
  931.     printf("Bug...\n");
  932.     
  933.     for (i = 0; i < top_bb; i++)
  934.     if (bb_stack[i].h == h)
  935.         return bb_stack + i;
  936.     if (!quiet_compile)
  937.     fprintf(stderr, "BB not found!\n");
  938.     return NULL;
  939. }
  940.  
  941. static int m68k_scan_block(struct hash_block *hb, int *movem_count)
  942. {
  943.     struct hash_entry *h = hb->he_first;
  944.     int i, iip, last_iip;
  945.     int changed, round;
  946.  
  947.     top_bb = 0;
  948.     
  949.     do {
  950.     struct bb_info *bb = bb_stack + top_bb;
  951.     bb->h = h;
  952.     bb->bb_next1 = NULL;
  953.     bb->bb_next2 = NULL;
  954.     h = h->next_same_block;
  955.     top_bb++;
  956.     } while (h != hb->he_first);
  957.     
  958.     qsort(bb_stack, top_bb, sizeof (struct bb_info), bb_compfn);
  959.  
  960.     *movem_count = 0;
  961.  
  962.     iip = 0;
  963.     for (i = 0; i < top_bb; i++) {
  964.     struct bb_info *bb = bb_stack + i;
  965.     uae_u8 *realpc = get_real_address(bb->h->addr);
  966.     uae_u8 *rpc_start = realpc;
  967.     uaecptr stop_addr = 0;
  968.     int live_at_start = 31, may_clear_las = 31;
  969.     struct insn_info_struct *prev_ii = NULL;
  970.  
  971.     if (i < top_bb - 1)
  972.         stop_addr = (bb+1)->h->addr;
  973.     bb->first_iip = iip;
  974.  
  975.     for (;;) {
  976.         struct insn_info_struct *thisii = insn_info + iip;
  977.         uaecptr thisinsn_addr = (realpc - rpc_start) + bb->h->addr;
  978.         uae_u8 *rpc_save = realpc;
  979.         struct instr *dp = translate_getnextinsn(&realpc);
  980.         uaecptr nextinsn_addr = (realpc - rpc_start) + bb->h->addr;
  981.         
  982.         int fset = dp->flagdead == -1 ? 31 : dp->flagdead;
  983.         int fuse = dp->flaglive == -1 ? 31 : dp->flaglive;
  984.         
  985.         if (thisinsn_addr == stop_addr) {
  986.         bb->bb_next1 = find_bb (find_hash (thisinsn_addr));
  987.         break;
  988.         }
  989.         
  990.         if (dp->mnemo == i_Scc || dp->mnemo == i_Bcc || dp->mnemo == i_DBcc) {
  991.         fset = 0, fuse = cc_flagmask_68k(dp->cc);
  992.         if (prev_ii && dp->mnemo != i_Scc) /* Don't use Scc here: ea can cause an exit */
  993.             prev_ii->ccuser_follows = 1;
  994.         }
  995.  
  996.         may_clear_las &= ~fuse;
  997.         live_at_start &= ~(fset & may_clear_las);
  998.         
  999.         thisii->dp = dp;
  1000.         thisii->address = thisinsn_addr;
  1001.         thisii->stop_translation = 0;
  1002.         thisii->ccuser_follows = 0;
  1003. /*        thisii->have_reginfo = 0;*/
  1004.         thisii->jump_target = 0;
  1005.         thisii->sync_cache = thisii->sync_flags = 0;
  1006.         thisii->flags_set = fset;
  1007.         thisii->flags_used = fuse;
  1008.         thisii->regs_set = 0;
  1009.         thisii->regs_used = 0;
  1010.         iip++;
  1011.         if (iip == MAX_TRANSLATE)
  1012.         return 0;
  1013.  
  1014.         if (dp->mnemo == i_RTS || dp->mnemo == i_RTE 
  1015.         || dp->mnemo == i_RTR || dp->mnemo == i_RTD
  1016.         || dp->mnemo == i_JMP || dp->mnemo == i_ILLG)
  1017.         {
  1018.         thisii->flags_used = 31;
  1019.         thisii->regs_used = 65535;
  1020.         thisii->stop_translation = dp->mnemo == i_RTS || dp->mnemo == i_JMP ? 2 : 1;
  1021.         break;
  1022.         }
  1023.         if (dp->mnemo == i_BSR || dp->mnemo == i_JSR)
  1024.         {
  1025.         thisii->flags_used = 31;
  1026.         thisii->regs_used = 65535;
  1027.         bb->can_compile_last = 1;
  1028.         bb->bb_next1 = find_bb (get_hash_for_func (nextinsn_addr, 1));
  1029.         if (bb->bb_next1 == NULL)
  1030.             thisii->stop_translation = 1;
  1031.         break;
  1032.         }
  1033.  
  1034.         if (dp->mnemo == i_DBcc) {
  1035.         uaecptr newaddr = thisinsn_addr + 2 + (uae_s16)((*(rpc_save+2) << 8) | *(rpc_save+3));
  1036.         bb->can_compile_last = 1;
  1037.         bb->bb_next1 = find_bb (get_hash_for_func (newaddr, 1));
  1038.         if (bb->bb_next1 == NULL)
  1039.             thisii->stop_translation = 1;
  1040.         bb->bb_next2 = find_bb (get_hash_for_func (nextinsn_addr, 1));
  1041.         if (bb->bb_next2 == NULL)
  1042.             thisii->stop_translation = 1;
  1043.         thisii->regs_used = 65535;
  1044.         break;
  1045.         }
  1046.         
  1047.         if (dp->mnemo == i_Bcc) {
  1048.         uaecptr newaddr;
  1049.         if (dp->smode == imm1)
  1050.             newaddr = thisinsn_addr + 2 + (uae_s16)((*(rpc_save+2) << 8) | *(rpc_save+3));
  1051.         else
  1052.             newaddr = thisinsn_addr + 2 + (uae_s8)dp->sreg;
  1053.         bb->can_compile_last = 1;
  1054.         bb->bb_next1 = find_bb(get_hash_for_func(newaddr, 1));
  1055.         if (bb->bb_next1 == NULL)
  1056.             thisii->stop_translation = 1;
  1057.         if (dp->cc != 0) {
  1058.             bb->bb_next2 = find_bb(get_hash_for_func(nextinsn_addr, 1));
  1059.             if (bb->bb_next2 == NULL)
  1060.             thisii->stop_translation = 1;
  1061.         }
  1062.         thisii->regs_used = 65535;
  1063.         break;
  1064.         }
  1065.  
  1066.         if (dp->mnemo == i_MVMLE || dp->mnemo == i_MVMEL) {
  1067.         uae_u16 regmask = (*(rpc_save + 2) << 8) | (*(rpc_save + 3));
  1068.         *movem_count += count_bits(regmask);
  1069.         if (dp->dmode == Apdi)
  1070.             regmask = bitswap(regmask);
  1071.         if (dp->mnemo == i_MVMLE)
  1072.             thisii->regs_used = regmask;
  1073.         else
  1074.             thisii->regs_set = regmask;
  1075.         }
  1076.  
  1077.         prev_ii = thisii;
  1078.     }
  1079.     bb->last_iip = iip - 1;
  1080.     bb->flags_live_at_start = live_at_start;
  1081.     }
  1082.     last_iip = iip;
  1083.     round = 0;
  1084.     do {
  1085.     changed = 0;
  1086.     for (i = 0; i < top_bb; i++) {
  1087.         struct bb_info *bb = bb_stack + i;
  1088.         int mnemo;
  1089.         int current_live;
  1090.         struct instr *dp;
  1091.     
  1092.         iip = bb->last_iip;
  1093.         mnemo = insn_info[iip].dp->mnemo;
  1094.  
  1095.         /* Fix up branches */
  1096.         if (round == 0 && (mnemo == i_DBcc || mnemo == i_Bcc)) {
  1097.         if (bb->bb_next1 != NULL) {
  1098.             insn_info[bb->last_iip].jumps_to = bb->bb_next1->first_iip;
  1099.             insn_info[bb->bb_next1->first_iip].jump_target = 1;
  1100.         }
  1101.         }
  1102.         
  1103.         /* And take care of flag life information */
  1104.         dp = insn_info[iip].dp;
  1105.         if (insn_info[iip].stop_translation)
  1106.         current_live = 31;
  1107.         else if (dp->mnemo == i_DBcc || dp->mnemo == i_Bcc) {
  1108.         current_live = 0;
  1109.         if (bb->bb_next1 != NULL)
  1110.             current_live |= bb->bb_next1->flags_live_at_start;
  1111.         if (bb->bb_next2 != NULL)
  1112.             current_live |= bb->bb_next2->flags_live_at_start;
  1113.         } else {
  1114.         if (bb->bb_next1 == NULL && bb->bb_next2 == NULL)
  1115.             fprintf(stderr, "Can't happen\n");
  1116.         current_live = 0;
  1117.         if (bb->bb_next1 != NULL)
  1118.             current_live |= bb->bb_next1->flags_live_at_start;
  1119.         if (bb->bb_next2 != NULL)
  1120.             current_live |= bb->bb_next2->flags_live_at_start;
  1121.         }
  1122.  
  1123.         do {
  1124.         insn_info[iip].flags_live_at_end = current_live;
  1125.         current_live &= ~insn_info[iip].flags_set;
  1126.         current_live |= insn_info[iip].flags_used;
  1127.         } while (iip-- != bb->first_iip);
  1128.  
  1129.         if (bb->flags_live_at_start != current_live && !quiet_compile)
  1130.         fprintf(stderr, "Fascinating %d!\n", round), changed = 1;
  1131.         bb->flags_live_at_start = current_live;
  1132.     }
  1133.     round++;
  1134.     } while (changed);
  1135.     return last_iip;
  1136. }
  1137.  
  1138. #define MAX_JSRS 4096 /* must be a power of two */
  1139.  
  1140. static uaecptr jsr_rets[MAX_JSRS];
  1141. static struct hash_entry *jsr_hash[MAX_JSRS];
  1142. static int jsr_num;
  1143. static struct hash_entry dummy_hash; /* This is for safety purposes only */
  1144.  
  1145.  
  1146. static void jsr_stack_init(void)
  1147. {
  1148.     jsr_num = 0;
  1149.     dummy_hash.execute = NULL;
  1150. }
  1151.  
  1152. void compiler_flush_jsr_stack(void)
  1153. {
  1154.     jsr_num = 0;
  1155. }
  1156.  
  1157. void m68k_do_rts(void)
  1158. {
  1159.     m68k_setpc(get_long(m68k_areg(regs, 7)));
  1160.     m68k_areg(regs, 7) += 4;
  1161.     if (jsr_num > 0)
  1162.     jsr_num--;
  1163. }
  1164.  
  1165. __inline__ void m68k_do_jsr(uaecptr dest)
  1166. {
  1167.     uae_u32 oldpc = m68k_getpc();
  1168.     struct hash_entry *h = find_hash(oldpc);
  1169.  
  1170.     if (jsr_num == MAX_JSRS)
  1171.     compiler_flush_jsr_stack();
  1172.     if (h == NULL) {
  1173.     jsr_hash[jsr_num] = &dummy_hash;
  1174.     jsr_rets[jsr_num++] = 0xC0DEDBAD;
  1175.     } else {
  1176.     jsr_hash[jsr_num] = h;
  1177.     jsr_rets[jsr_num++] = oldpc;
  1178.     }
  1179.     m68k_areg(regs, 7) -= 4;
  1180.     put_long(m68k_areg(regs, 7), oldpc);
  1181.     m68k_setpc(dest);
  1182. }
  1183.  
  1184. void m68k_do_bsr(uae_s32 offset)
  1185. {
  1186.     m68k_do_jsr(m68k_getpc() + offset);
  1187. }
  1188.  
  1189. /* Here starts the actual compiling part */
  1190.  
  1191. static char *compile_current_addr;
  1192. static char *compile_last_addr;
  1193.  
  1194. static __inline__ void assemble(uae_u8 a)
  1195. {
  1196.     if (compile_current_addr < compile_last_addr) {
  1197.     *compile_current_addr++ = a;
  1198.     } else {
  1199.     compile_failure = 1;
  1200.     }
  1201. }
  1202.  
  1203. static __inline__ void assemble_ulong(uae_u32 a)
  1204. {
  1205.     assemble(a);
  1206.     assemble(a >> 8);
  1207.     assemble(a >> 16);
  1208.     assemble(a >> 24);
  1209. }
  1210.  
  1211. static __inline__ void assemble_ulong_68k(uae_u32 a)
  1212. {
  1213.     assemble(a >> 24);
  1214.     assemble(a >> 16);
  1215.     assemble(a >> 8);
  1216.     assemble(a);
  1217. }
  1218.  
  1219. static __inline__ void assemble_uword(uae_u16 a)
  1220. {
  1221.     assemble(a);
  1222.     assemble(a >> 8);
  1223. }
  1224.  
  1225. static __inline__ void assemble_long(void *a)
  1226. {
  1227.     assemble_ulong((uae_u32)a);
  1228. }
  1229.  
  1230. static __inline__ void compile_org(char *addr)
  1231. {
  1232.     compile_current_addr = addr;
  1233. }
  1234.  
  1235. static __inline__ char *compile_here(void)
  1236. {
  1237.     return compile_current_addr;
  1238. }
  1239.  
  1240. #define r_EAX 0
  1241. #define r_ECX 1
  1242. #define r_EDX 2
  1243. #define r_EBX 3
  1244. #define r_ESP 4
  1245. #define r_EBP 5
  1246. #define r_ESI 6
  1247. #define r_EDI 7
  1248.  
  1249. #define r_AH 0x84
  1250. #define r_CH 0x85
  1251. #define r_DH 0x86
  1252. #define r_BH 0x87
  1253.  
  1254. #define ALL_X86_REGS 255
  1255. #define ADDRESS_X86_REGS ((1 << r_EBP) | (1 << r_ESI) | (1 << r_EDI))
  1256. #define DATA_X86_REGS ((1 << r_EAX) | (1 << r_EDX) | (1 << r_EBX) | (1 << r_ECX))
  1257.  
  1258. #define BO_NORMAL 0
  1259. #define BO_SWAPPED_LONG 1
  1260. #define BO_SWAPPED_WORD 2
  1261.  
  1262. struct register_mapping {
  1263.     int dreg_map[8], areg_map[8]; /* 68000 register cache */
  1264.     int x86_const_offset[8];
  1265.     int x86_dirty[8];
  1266.     int x86_cache_reg[8]; /* Regs used for the 68000 register cache */
  1267.     int x86_cr_type[8]; /* Caching data or address register? */
  1268.     int x86_locked[8]; /* Regs used for some purpose */
  1269.     int x86_users[8];
  1270.     int x86_byteorder[8];
  1271.     int x86_verified[8];
  1272. };
  1273.  
  1274. /*
  1275.  * First, code to compile some primitive x86 instructions
  1276.  */
  1277.  
  1278. static void compile_lea_reg_with_offset(int dstreg, int srcreg, uae_u32 srcoffs)
  1279. {
  1280.     assemble(0x8D);
  1281.     if (srcreg == -2) {
  1282.     assemble(0x05 + 8*dstreg);
  1283.     assemble_ulong(srcoffs);
  1284.     } else if ((uae_s32)srcoffs >= -128 && (uae_s32)srcoffs <= 127) {
  1285.     assemble(0x40 + 8*dstreg + srcreg);
  1286.     assemble(srcoffs);
  1287.     } else {
  1288.     assemble(0x80 + 8*dstreg + srcreg);
  1289.     assemble_ulong(srcoffs);
  1290.     }
  1291. }
  1292.  
  1293. static void compile_move_reg_reg(int dstreg, int srcreg, wordsizes size)
  1294. {
  1295.     if (size == sz_byte
  1296.     && (((1 << dstreg) & DATA_X86_REGS) == 0
  1297.         || ((1 << srcreg) & DATA_X86_REGS) == 0))
  1298.     {
  1299.     fprintf(stderr, "Moving wrong register types!\n");
  1300.     }
  1301.     if (size == sz_word)
  1302.     assemble(0x66);
  1303.     if (size == sz_byte)
  1304.     assemble(0x88);
  1305.     else
  1306.     assemble(0x89);
  1307.     assemble(0xC0 + dstreg + 8*srcreg);
  1308. }
  1309.  
  1310. static void compile_move_between_reg_mem_regoffs(int dstreg, int srcreg,
  1311.                          uae_u32 srcoffs, wordsizes size,
  1312.                          int code)
  1313. {
  1314.     if (size == sz_byte && (dstreg & 0x80) != 0)
  1315.     dstreg &= ~0x80;
  1316.     else if ((size == sz_byte
  1317.           && ((1 << dstreg) & DATA_X86_REGS) == 0)
  1318.          || (size != sz_byte && (dstreg & 0x80) != 0))
  1319.     {
  1320.     fprintf(stderr, "Moving wrong register types!\n");
  1321.     }
  1322.     if (size == sz_word)
  1323.     assemble(0x66);
  1324.     if (size == sz_byte)
  1325.     assemble(code);
  1326.     else
  1327.     assemble(code + 1);
  1328.     
  1329.     if (srcreg == -2) {
  1330.     assemble(0x05 + 8*dstreg);
  1331.     assemble_ulong(srcoffs);
  1332.     } else if ((uae_s32)srcoffs >= -128 && (uae_s32)srcoffs <= 127) {
  1333.     assemble(0x40 + 8*dstreg + srcreg);
  1334.     assemble(srcoffs);
  1335.     } else {
  1336.     assemble(0x80 + 8*dstreg + srcreg);
  1337.     assemble_ulong(srcoffs);
  1338.     }
  1339. }
  1340.  
  1341. static void compile_move_reg_from_mem_regoffs(int dstreg, int srcreg, 
  1342.                           uae_u32 srcoffs, wordsizes size)
  1343. {
  1344.     compile_move_between_reg_mem_regoffs(dstreg, srcreg, srcoffs, size, 0x8A);
  1345. }
  1346.  
  1347. static void compile_move_reg_to_mem_regoffs(int dstreg, uae_u32 dstoffs, 
  1348.                         int srcreg, wordsizes size)
  1349. {
  1350.     compile_move_between_reg_mem_regoffs(srcreg, dstreg, dstoffs, size, 0x88);
  1351. }
  1352.  
  1353. static void compile_byteswap(int x86r, wordsizes size, int save_flags)
  1354. {
  1355.     switch(size) {
  1356.      case sz_word:
  1357.     if (save_flags)
  1358.         assemble(0x9C);
  1359.     assemble(0x66); /* rolw $8,x86r */
  1360.     assemble(0xC1);
  1361.     assemble(0xC0 + x86r);
  1362.     assemble(8);
  1363.     if (save_flags)
  1364.         assemble(0x9D);
  1365.     break;
  1366.      case sz_long:
  1367.     assemble(0x0F); /* bswapl x86r */
  1368.     assemble(0xC8+x86r);
  1369.     break;
  1370.      default:
  1371.     break;
  1372.     }
  1373. }
  1374.  
  1375. static void compile_force_byteorder(struct register_mapping *map, int x86r,
  1376.                     int desired_bo, int save_flags)
  1377. {
  1378.     if (x86r < 0 || map->x86_byteorder[x86r] == desired_bo)
  1379.     return;
  1380.     
  1381.     if (map->x86_byteorder[x86r] == BO_SWAPPED_LONG)
  1382.     compile_byteswap(x86r, sz_long, save_flags);
  1383.     else if (map->x86_byteorder[x86r] == BO_SWAPPED_WORD)
  1384.     compile_byteswap(x86r, sz_word, save_flags);
  1385.     
  1386.     if (desired_bo == BO_SWAPPED_LONG)
  1387.     compile_byteswap(x86r, sz_long, save_flags);
  1388.     else if (desired_bo == BO_SWAPPED_WORD)
  1389.     compile_byteswap(x86r, sz_word, save_flags);
  1390.     map->x86_byteorder[x86r] = desired_bo;
  1391. }
  1392.  
  1393. /* Add a constant offset to a x86 register. If it's in the cache, make sure
  1394.  * we update the const_offset value. The flags are unaffected by this */
  1395.  
  1396. static void compile_offset_reg(struct register_mapping *map, int x86r, 
  1397.                    uae_u32 offset)
  1398. {
  1399.     int cached_68k;
  1400.     
  1401.     if (offset == 0 || x86r == -1 || x86r == -2)
  1402.     return;
  1403.  
  1404.     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1405.     cached_68k = map->x86_cache_reg[x86r];
  1406.     if (cached_68k != -1) {
  1407.     map->x86_const_offset[x86r] -= offset;
  1408.     map->x86_dirty[x86r] = 1;
  1409.     }
  1410.     compile_lea_reg_with_offset(x86r, x86r, offset);
  1411. }
  1412.  
  1413. static int get_unused_x86_register(struct register_mapping *map)
  1414. {
  1415.     int x86r;
  1416.     for (x86r = 0; x86r < 24; x86r++) {
  1417.     if (map->x86_cache_reg[x86r] != -1)
  1418.         continue;
  1419.     if (map->x86_users[x86r] > 0)
  1420.         continue;
  1421.     
  1422.     map->x86_verified[x86r] = 0;
  1423.     map->x86_byteorder[x86r] = BO_NORMAL;
  1424.     return x86r;
  1425.     }
  1426.     return -1;
  1427. }
  1428.  
  1429. /*
  1430.  * sync_reg() may not touch the flags
  1431.  * If may_clobber is 1 and the reg had an offset, the reg will be offsetted
  1432.  * by this function
  1433.  */
  1434. static void sync_reg(struct register_mapping *map, int x86r, void *m68kr, 
  1435.              uae_u32 offset, int dirty, int may_clobber)
  1436. {
  1437.     if (dirty || offset != 0)
  1438.     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1439.     if (offset != 0) {
  1440.     if (may_clobber) {
  1441.         compile_lea_reg_with_offset(x86r, x86r, offset);
  1442.         dirty = 1;
  1443.     } else {
  1444.         int tmpr = get_unused_x86_register(map);
  1445.         if (tmpr != -1) { 
  1446.         compile_lea_reg_with_offset(tmpr, x86r, offset);
  1447.         x86r = tmpr;
  1448.         dirty = 1;
  1449.         } else {
  1450.         compile_lea_reg_with_offset(x86r, x86r, offset);
  1451.         assemble(0x89);          /* movl x86r,m68kr */
  1452.         assemble(0x05 + (x86r << 3)); 
  1453.         assemble_long(m68kr);
  1454.         compile_lea_reg_with_offset(x86r, x86r, -offset);
  1455.         return;
  1456.         }
  1457.     }
  1458.     }
  1459.     if (dirty) {
  1460.     assemble(0x89);          /* movl x86r,m68kr */
  1461.     assemble(0x05 + (x86r << 3)); 
  1462.     assemble_long(m68kr);
  1463.     }
  1464. }
  1465.  
  1466. static void sync_reg_cache(struct register_mapping *map, int flush)
  1467. {
  1468.     int i;
  1469.  
  1470.     for (i = 0; i < 8; i++) {
  1471.     int cr68k = map->x86_cache_reg[i];
  1472.     if (cr68k != -1) {
  1473.         if (map->x86_cr_type[i] == 1) {
  1474.         sync_reg(map, i, regs.regs + cr68k, map->x86_const_offset[i], map->x86_dirty[i], 1);
  1475.         if (flush)
  1476.             map->dreg_map[cr68k] = -1;
  1477.         } else {
  1478.         sync_reg(map, i, regs.regs + 8 + cr68k, map->x86_const_offset[i], map->x86_dirty[i], 1);
  1479.         if (flush)
  1480.             map->areg_map[cr68k] = -1;
  1481.         }
  1482.         if (flush)
  1483.         map->x86_cache_reg[i] = -1;
  1484.         map->x86_const_offset[i] = 0;
  1485.     }
  1486.     }
  1487.     memset(map->x86_dirty, 0, sizeof map->x86_dirty);
  1488. }
  1489.  
  1490. static void remove_x86r_from_cache(struct register_mapping *map, int x86r, 
  1491.                    int may_clobber)
  1492. {
  1493.     int j;
  1494.     int reg_68k;
  1495.     
  1496.     if (x86r == -1)
  1497.     return;
  1498.  
  1499.     reg_68k = map->x86_cache_reg[x86r];
  1500.     
  1501.     if (reg_68k == -1)
  1502.     return;
  1503.     
  1504.     if (map->x86_cr_type[x86r] == 1) {
  1505.     map->dreg_map[reg_68k] = -1;
  1506.     sync_reg(map, x86r, regs.regs + reg_68k, map->x86_const_offset[x86r],
  1507.          map->x86_dirty[x86r], may_clobber);
  1508.     } else {
  1509.     map->areg_map[reg_68k] = -1;
  1510.     sync_reg(map, x86r, regs.regs + 8 + reg_68k,  map->x86_const_offset[x86r],
  1511.          map->x86_dirty[x86r], may_clobber);
  1512.     }
  1513.     map->x86_dirty[x86r] = 0;
  1514.     map->x86_cache_reg[x86r] = -1;
  1515.     map->x86_const_offset[x86r] = 0;
  1516.     map->x86_verified[x86r] = 0;
  1517.     map->x86_byteorder[x86r] = BO_NORMAL;
  1518. }
  1519.  
  1520. static int get_free_x86_register(struct register_mapping *map,
  1521.                  int preferred_mask)
  1522. {
  1523.     int cnt;
  1524.     for (cnt = 0; cnt < 24; cnt++) {
  1525.     int x86r = cnt & 7;
  1526.     /* In the first two passes, try to get one of the preferred regs */
  1527.     if (cnt < 16 && ((1 << x86r) & preferred_mask) == 0)
  1528.         continue;
  1529.     /* In the first pass, don't discard any registers from the cache */
  1530.     if (cnt < 8 && map->x86_cache_reg[x86r] != -1)
  1531.         continue;
  1532.     /* Never use locked registers */
  1533.     if (map->x86_users[x86r] > 0)
  1534.         continue;
  1535.  
  1536.     remove_x86r_from_cache(map, x86r, 1);
  1537.     map->x86_dirty[x86r] = 0;
  1538.     map->x86_cache_reg[x86r] = -1;
  1539.     map->x86_const_offset[x86r] = 0;
  1540.     map->x86_verified[x86r] = 0;
  1541.     map->x86_byteorder[x86r] = BO_NORMAL;
  1542.     return x86r;
  1543.     }
  1544.     printf("Out of registers!\n");
  1545.     return -1;
  1546. }
  1547.  
  1548. static int get_typed_x86_register(struct register_mapping *map,
  1549.                   int preferred_mask)
  1550. {
  1551.     int cnt;
  1552.     for (cnt = 0; cnt < 16; cnt++) {
  1553.     int x86r = cnt & 7;
  1554.     /* Get one of the preferred regs */
  1555.     if (((1 << x86r) & preferred_mask) == 0)
  1556.         continue;
  1557.     /* In the first pass, don't discard any registers from the cache */
  1558.     if (cnt < 8 && map->x86_cache_reg[x86r] != -1)
  1559.         continue;
  1560.     /* Never use locked registers */
  1561.     if (map->x86_users[x86r] > 0)
  1562.         continue;
  1563.  
  1564.     remove_x86r_from_cache(map, x86r, 1);
  1565.     map->x86_dirty[x86r] = 0;
  1566.     map->x86_cache_reg[x86r] = -1;
  1567.     map->x86_const_offset[x86r] = 0;
  1568.     map->x86_verified[x86r] = 0;
  1569.     map->x86_byteorder[x86r] = BO_NORMAL;
  1570.     return x86r;
  1571.     }
  1572.     printf("Out of type registers!\n");
  1573.     return -1;
  1574. }
  1575.  
  1576. static void compile_unlock_reg(struct register_mapping *map, int reg)
  1577. {
  1578.     if (reg >= 0) {
  1579.     if (--map->x86_users[reg] == 0)
  1580.         map->x86_locked[reg] = 0;
  1581.  
  1582.     }
  1583. }
  1584.  
  1585. static void lock_reg(struct register_mapping *map, int x86r, int lock_type)
  1586. {
  1587. #if 1
  1588.     switch (map->x86_locked[x86r]) {
  1589.      case 0:
  1590.     if (map->x86_users[x86r] != 0)
  1591.         printf("Users for an unlocked reg!\n");
  1592.     break;
  1593.      case 1:
  1594.     if (lock_type == 2)
  1595.         printf("Locking shared reg for exclusive use!\n");
  1596.     break;
  1597.      case 2:
  1598.     printf("Locking exclusive reg!\n");
  1599.     break;
  1600.      default:
  1601.     printf("Unknown lock?\n");
  1602.     break;
  1603.     }
  1604. #endif
  1605.     map->x86_locked[x86r] = lock_type;
  1606.     map->x86_users[x86r]++;
  1607. }
  1608.  
  1609. static int get_and_lock_68k_reg(struct register_mapping *map, int reg, int is_dreg,
  1610.                 int preferred, int no_offset, int lock_type)
  1611. {
  1612.     int x86r;
  1613.     int *regmap;
  1614.     uae_u32 *reghome;
  1615.     uae_u32 const_off = 0;
  1616.     
  1617.     if (reg < 0 || reg > 7) {
  1618.     printf("Mad compiler disease\n");
  1619.     return 0;
  1620.     }
  1621.  
  1622.     if (is_dreg)
  1623.     regmap = map->dreg_map, reghome = regs.regs;
  1624.     else
  1625.     regmap = map->areg_map, reghome = regs.regs + 8;
  1626.     
  1627.     if (preferred == 0)
  1628.     preferred = ALL_X86_REGS;
  1629.     
  1630.     x86r = regmap[reg];
  1631.     if (x86r == -1) {
  1632.     x86r = get_free_x86_register(map, preferred);
  1633.     assemble(0x8B); assemble(0x05 + (x86r << 3)); /* movl regs.d[reg],x86r */
  1634.     assemble_long(reghome + reg);
  1635.     map->x86_cache_reg[x86r] = reg;
  1636.     map->x86_cr_type[x86r] = is_dreg;
  1637.     map->x86_const_offset[x86r] = 0;
  1638.     map->x86_dirty[x86r] = 0;
  1639.     map->x86_verified[x86r] = 0;
  1640.     map->x86_byteorder[x86r] = BO_NORMAL;
  1641.     regmap[reg] = x86r;
  1642.     } else {
  1643.     const_off = map->x86_const_offset[x86r];
  1644.     
  1645.     if (map->x86_locked[x86r] == 2
  1646.         || (map->x86_locked[x86r] == 1 && (lock_type == 2 || (const_off != 0 && no_offset))))
  1647.     {
  1648.         int newr;
  1649.         int old_dirty = 0;
  1650.         int old_verified;
  1651.         int old_bo;
  1652.     
  1653.         newr = get_free_x86_register(map, preferred);
  1654.         if (const_off == 0) {
  1655.         compile_move_reg_reg(newr, x86r, sz_long);
  1656.         } else {
  1657.         compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1658.         compile_lea_reg_with_offset(newr, x86r, const_off);
  1659.         old_dirty = 1;
  1660.         const_off = 0;
  1661.         }
  1662.         /* Remove old reg from cache... */
  1663.         map->x86_cache_reg[x86r] = -1;
  1664.         map->x86_cr_type[x86r] = is_dreg;
  1665.         map->x86_const_offset[x86r] = 0;
  1666.         old_dirty |= map->x86_dirty[x86r];
  1667.         old_verified = map->x86_verified[x86r];
  1668.         old_bo = map->x86_byteorder[x86r];
  1669.         map->x86_verified[x86r] = 0;
  1670.         map->x86_dirty[x86r] = 0;
  1671.         x86r = newr;
  1672.         /* ... and make the new one the cache register */
  1673.         map->x86_cache_reg[x86r] = reg;
  1674.         map->x86_cr_type[x86r] = is_dreg;
  1675.         map->x86_const_offset[x86r] = 0;
  1676.         map->x86_dirty[x86r] = old_dirty;
  1677.         map->x86_verified[x86r] = old_verified;
  1678.         map->x86_byteorder[x86r] = old_bo;
  1679.         regmap[reg] = x86r;
  1680.     }
  1681.     }
  1682.     if (no_offset && const_off != 0) {
  1683.     if (map->x86_locked[x86r] != 0)
  1684.         printf("modifying locked reg\n");
  1685.     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1686.     compile_lea_reg_with_offset(x86r, x86r, map->x86_const_offset[x86r]);
  1687.     map->x86_const_offset[x86r] = 0;
  1688.     map->x86_dirty[x86r] = 1;
  1689.     }
  1690.     lock_reg(map, x86r, lock_type);
  1691.     return x86r;
  1692. }
  1693.  
  1694. /*
  1695.  * Move a constant to a register. Don't do anything if we already have a
  1696.  * register, even if it is offset by a constant
  1697.  */
  1698.  
  1699. static int compile_force_const_reg(struct register_mapping *map, int x86r,
  1700.                    uae_u32 *offs, int desired)
  1701. {
  1702.     int newr = x86r;
  1703.  
  1704.     if (newr == -2) {
  1705.     if (desired == 0)
  1706.         newr = get_free_x86_register(map, ALL_X86_REGS);
  1707.     else
  1708.         newr = get_typed_x86_register(map, desired);
  1709.  
  1710.     assemble(0xB8 + newr);
  1711.     assemble_ulong(*offs);
  1712.     *offs = 0;
  1713.     }
  1714.     map->x86_users[newr]++;
  1715.     return newr;
  1716. }
  1717.  
  1718. static void compile_extend_long(struct register_mapping *map, int x86r,
  1719.                 wordsizes size)
  1720. {
  1721.     if (x86r < 0) {
  1722.     printf("Bad reg in extend_long\n");
  1723.     return;
  1724.     }
  1725.     
  1726.     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1727.  
  1728.     if (size != sz_long) {
  1729.     if (x86r == r_EAX && size == sz_word) {
  1730.         assemble(0x98); /* cwtl */
  1731.     } else {
  1732.         assemble(0x0F);
  1733.         if (size == sz_byte) {
  1734.         assemble(0xBE);
  1735.         } else {
  1736.         assemble(0xBF);
  1737.         }
  1738.         assemble(0xC0 + x86r*9);
  1739.     }
  1740.     }
  1741. }
  1742.  
  1743. struct ea_info {
  1744.     int reg;
  1745.     amodes mode;
  1746.     wordsizes size;
  1747.     int address_reg;    /* The x86 reg holding the address, or -1 if ea doesn't refer to memory
  1748.              * -2 if it refers to memory, but only with a constant address */
  1749.     uae_u32 addr_const_off; /* Constant offset to the address */
  1750.     int data_reg;         /* The x86 reg that holds the data. -1 if data is not present yet. 
  1751.                * -2 if data is constant */
  1752.     uae_u32 data_const_off;
  1753.     int flags;            /* Extra info. Contains the dp field of d8r modes */
  1754.     int purpose;
  1755. };
  1756.  
  1757. static void init_eainfo(struct ea_info *eai)
  1758. {
  1759.     eai->address_reg = -1;
  1760.     eai->addr_const_off = 0;
  1761.     eai->data_reg = -1;
  1762.     eai->data_const_off = 0;
  1763. }
  1764.  
  1765. struct insn_reg_needs {
  1766.     int checkpoint_no;
  1767.     int dreg_needed[8], areg_needed[8];
  1768.     int dreg_mask[8], areg_mask[8];
  1769. };
  1770.  
  1771. /*
  1772.  * This structure holds information about predec/postinc addressing modes.
  1773.  */
  1774.  
  1775. struct pid_undo {
  1776.     int used;
  1777.     int x86r[2];
  1778.     int m68kr[2];
  1779.     int dirty[2];
  1780.     int offs[2];
  1781. };
  1782.  
  1783. static void add_undo(struct pid_undo *pud, int x86r, int m68kr, int offs,
  1784.              int dirty)
  1785. {
  1786.     int i;
  1787.     for (i = 0; i < pud->used; i++)
  1788.     if (pud->m68kr[i] == m68kr)
  1789.         return;
  1790.     pud->m68kr[i] = m68kr;
  1791.     pud->x86r[i] = x86r;
  1792.     pud->offs[i] = offs;
  1793.     pud->dirty[i] = dirty;
  1794.     pud->used++;
  1795. }
  1796.  
  1797. /*
  1798.  * Lock previous contents of address registers used in predec/postinc modes
  1799.  * for generate_possible_exit().
  1800.  */
  1801.  
  1802. static void compile_prepare_undo(struct register_mapping *map, amodes mode,
  1803.                   int reg, struct pid_undo *pud)
  1804. {
  1805.     int x86r;
  1806.  
  1807.     switch(mode){
  1808.      default:
  1809.     break;
  1810.     
  1811.      case Apdi:
  1812.     x86r = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1813.     /* This saves recording the byteorder in the pud structure, and we'll
  1814.      * need it in normal byteorder anyway */
  1815.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1816.     /* 
  1817.      * Add this reg with its current offset to the undo buffer.
  1818.      * Since we have locked it, we are certain that it will not be
  1819.      * modified.
  1820.      */
  1821.     add_undo(pud, x86r, reg, map->x86_const_offset[x86r], map->x86_dirty[x86r]);
  1822.     break;
  1823.     
  1824.      case Aipi:
  1825.     x86r = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1826.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1827.     add_undo(pud, x86r, reg, map->x86_const_offset[x86r], map->x86_dirty[x86r]);
  1828.     break;
  1829.     }
  1830. }
  1831.  
  1832. /*
  1833.  * Load all the registers absolutely needed to calculate and verify thea
  1834.  * address. Load other registers if convenient.
  1835.  * This contains a fair amount of magic to get the register cache working right.
  1836.  */
  1837.  
  1838. static void compile_prepareea(struct register_mapping *map, amodes mode,
  1839.                   int reg, wordsizes size, uae_u8 **pcpp, uaecptr pca,
  1840.                   struct ea_info *eainf, int eaino, int ea_purpose,
  1841.                   int pidmult)
  1842. {
  1843.     struct ea_info *eai = eainf + eaino;
  1844.     int pdival = size == sz_byte && reg != 7 ? 1 : size == sz_long ? 4 : 2;
  1845.     uae_u8 *p = *pcpp;
  1846.     uae_u16 dp;
  1847.     int r;
  1848.     int x86r, tmpr;
  1849.  
  1850.     pdival *= pidmult;
  1851.     
  1852.     init_eainfo(eai);
  1853.     eai->mode = mode;
  1854.     eai->size = size;
  1855.     eai->reg = reg;
  1856.     
  1857.     switch(mode){
  1858.      case Dreg:
  1859.      case Areg:
  1860.     break;
  1861.     
  1862.      case Ad16:
  1863.     eai->addr_const_off = (uae_s16)do_get_mem_word((uae_u16 *)p);
  1864.     (*pcpp) += 2; p += 2;
  1865.     x86r = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1866.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1867.     eai->addr_const_off += map->x86_const_offset[x86r];
  1868.     break;
  1869.  
  1870.      case Aind:
  1871.     x86r = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1872.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1873.     eai->addr_const_off = map->x86_const_offset[x86r];
  1874.     break;
  1875.     
  1876.      case Apdi:
  1877.     x86r = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1878.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1879.     map->x86_const_offset[x86r] -= pdival;
  1880.     eai->addr_const_off = map->x86_const_offset[x86r];
  1881.     break;
  1882.     
  1883.      case Aipi:
  1884.     x86r = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1885.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1886.     eai->addr_const_off = map->x86_const_offset[x86r];
  1887.     map->x86_const_offset[x86r] += pdival;
  1888.     break;
  1889.  
  1890.      case Ad8r:
  1891.     dp = (uae_s16)do_get_mem_word((uae_u16 *)p);
  1892.     r = (dp & 0x7000) >> 12;
  1893.     (*pcpp) += 2; p += 2;    
  1894.     
  1895.     tmpr = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1896.     compile_force_byteorder(map, tmpr, BO_NORMAL, 0);
  1897.     eai->addr_const_off = map->x86_const_offset[tmpr] + (uae_s8)dp;
  1898.  
  1899.     if (dp & 0x800) {
  1900.         x86r = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, ADDRESS_X86_REGS, 0, 2);
  1901.         remove_x86r_from_cache(map, x86r, 0);
  1902.         compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1903.         eai->addr_const_off += map->x86_const_offset[x86r];
  1904.     } else {
  1905.         x86r = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, ADDRESS_X86_REGS, 1, 2);
  1906.         remove_x86r_from_cache(map, x86r, 0);
  1907.         compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1908.     }
  1909.     eai->address_reg = x86r;
  1910.     
  1911.     r = (dp & 0x7000) >> 12;
  1912.  
  1913.     if (dp & 0x800) {
  1914.         if (eai->addr_const_off == 0) {
  1915.         assemble(0x03); assemble(0xC0 + tmpr + x86r*8); /* addl basereg,addrreg */
  1916.         } else if ((uae_s32)eai->addr_const_off >= -128 && (uae_s32)eai->addr_const_off <= 127) {
  1917.         assemble(0x8D); 
  1918.         assemble(0x44 + x86r*8); /* leal disp8(dispreg,basereg),dispreg */
  1919.         assemble(x86r*8 + tmpr);
  1920.         assemble(eai->addr_const_off);
  1921.         } else {
  1922.         assemble(0x8D);
  1923.         assemble(0x84 + x86r*8); /* leal disp32(dispreg,basereg),dispreg */
  1924.         assemble(x86r*8 + tmpr);
  1925.         assemble_ulong(eai->addr_const_off);
  1926.         }
  1927.         eai->addr_const_off = 0;
  1928.     } else {
  1929.         assemble(0x0F); assemble(0xBF);
  1930.         assemble(0xC0 + x86r*9); /* movswl dispreg,addrreg */
  1931.         assemble(0x03); assemble(0xC0 + tmpr + x86r*8); /* addl basereg,addrreg */
  1932.     }
  1933.     compile_unlock_reg(map, tmpr);
  1934.     break;
  1935.  
  1936.      case PC8r:
  1937.     dp = (uae_s16)do_get_mem_word((uae_u16 *)p);
  1938.     (*pcpp) += 2; p += 2;
  1939.     r = (dp & 0x7000) >> 12;
  1940.     eai->addr_const_off = pca + (uae_s8)dp;
  1941.     if (dp & 0x800) {
  1942.         x86r = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, ADDRESS_X86_REGS, 0, 1);
  1943.         remove_x86r_from_cache(map, x86r, 0);
  1944.         compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1945.         eai->addr_const_off += map->x86_const_offset[x86r];
  1946.     } else {
  1947.         x86r = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, ADDRESS_X86_REGS, 1, 2);
  1948.         remove_x86r_from_cache(map, x86r, 0);
  1949.         compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1950.  
  1951.         assemble(0x0F); assemble(0xBF);
  1952.         assemble(0xC0 + x86r*9); /* movswl dispreg,addrreg */
  1953.     }
  1954.     eai->address_reg = x86r;
  1955.     break;
  1956.     
  1957.      case PC16:
  1958.     eai->addr_const_off = pca + (uae_s16)do_get_mem_word((uae_u16 *)p);
  1959.     eai->address_reg = -2;
  1960.     (*pcpp) += 2; p += 2;
  1961.     break;
  1962.     
  1963.      case absw:
  1964.     eai->addr_const_off = (uae_s16)do_get_mem_word((uae_u16 *)p);
  1965.     eai->address_reg = -2;
  1966.     (*pcpp) += 2; p += 2;
  1967.     break;
  1968.  
  1969.      case absl:
  1970.     eai->addr_const_off = (uae_s32)do_get_mem_long((uae_u32 *)p);
  1971.     eai->address_reg = -2;
  1972.     (*pcpp) += 4; p += 4;
  1973.     break;
  1974.  
  1975.      case imm:
  1976.     if (size == sz_long)
  1977.         goto imm2_const;
  1978.     if (size == sz_word)
  1979.         goto imm1_const;
  1980.     
  1981.     /* fall through */
  1982.      case imm0:
  1983.     eai->data_const_off = (uae_s8)*(p+1);
  1984.     eai->data_reg = -2;
  1985.     (*pcpp) += 2; p += 2;
  1986.     break;
  1987.  
  1988.      case imm1:
  1989.     imm1_const:
  1990.     eai->data_const_off = (uae_s16)do_get_mem_word((uae_u16 *)p);
  1991.     eai->data_reg = -2;
  1992.     (*pcpp) += 2; p += 2;
  1993.     break;
  1994.  
  1995.      case imm2:
  1996.     imm2_const:
  1997.     eai->data_const_off = (uae_s32)do_get_mem_long((uae_u32 *)p);
  1998.     eai->data_reg = -2;
  1999.     (*pcpp) += 4; p += 4;
  2000.     break;
  2001.  
  2002.      case immi:
  2003.     eai->data_const_off = (uae_s8)reg;
  2004.     eai->data_reg = -2;
  2005.     break;
  2006.  
  2007.      default:
  2008.     break;
  2009.     }
  2010.     eai->purpose = ea_purpose;
  2011. }
  2012.  
  2013. static void compile_get_excl_lock(struct register_mapping *map, struct ea_info *eai)
  2014. {
  2015.     int x86r = eai->data_reg;
  2016.     
  2017.     if (x86r >= 0 && map->x86_locked[x86r] == 1) {
  2018.     int newr;
  2019.     if (eai->size == sz_byte)
  2020.         newr = get_typed_x86_register(map, DATA_X86_REGS);
  2021.     else
  2022.         newr = get_free_x86_register(map, ALL_X86_REGS);
  2023.     
  2024.     compile_move_reg_reg(newr, x86r, sz_long);
  2025.     eai->data_reg = newr;
  2026.     lock_reg(map, eai->data_reg, 2);
  2027.     }
  2028. }
  2029.  
  2030. /*
  2031.  * Some functions to assemble some 386 opcodes which have a similar
  2032.  * structure (ADD, AND, OR, etc.). These take source and destination
  2033.  * addressing modes, check their validity and assemble a complete
  2034.  * 386 instruction.
  2035.  */
  2036.  
  2037. static __inline__ int rmop_long(struct ea_info *eai)
  2038. {
  2039.     if (eai->data_reg == -2)
  2040.     printf("rmop for const\n");
  2041.     else if (eai->data_reg == -1) {
  2042.     if (eai->address_reg == -2)
  2043.         return 5;
  2044.     if (eai->address_reg == -1) {
  2045.         /* This must be a 68k register in its home location */
  2046.         return 5;
  2047.     }
  2048. #if 0 /* We need to add address_space... */
  2049.     if (eai->addr_const_off == 0 && eai->address_reg != r_EBP) {
  2050.         return eai->address_reg;
  2051.     }
  2052.     else if ((uae_s32)eai->addr_const_off >= -128 && (uae_s32)eai->addr_const_off <= 127) {
  2053.         return eai->address_reg | 0x40;
  2054.     }
  2055. #endif
  2056.     return eai->address_reg | 0x80;
  2057.     } else {
  2058.     if (eai->size == sz_byte && ((1 << eai->data_reg) & DATA_X86_REGS) == 0)
  2059.         printf("wrong type reg in rmop\n");
  2060.     if (eai->data_const_off != 0)
  2061.         printf("data_const_off in rmop\n");
  2062.     return 0xC0 + eai->data_reg;
  2063.     }
  2064.     return 0;
  2065. }
  2066.  
  2067. static __inline__ int rmop_short(struct ea_info *eai)
  2068. {
  2069.     if (eai->data_reg == -2)
  2070.     printf("rmop_short for const\n");
  2071.     else if (eai->data_reg == -1) {
  2072.     printf("rmop_short for mem\n");
  2073.     } else {
  2074.     if (eai->size == sz_byte && ((1 << eai->data_reg) & DATA_X86_REGS) == 0)
  2075.         printf("wrong type reg in rmop_short\n");
  2076.     if (eai->data_const_off != 0)
  2077.         printf("data_const_off in rmop_short\n");
  2078.     return eai->data_reg*8;
  2079.     }
  2080.     return 0;
  2081. }
  2082.  
  2083. static __inline__ void rmop_finalize(struct ea_info *eai) 
  2084. {
  2085.     if (eai->data_reg == -2)
  2086.     assemble_ulong(eai->data_const_off);
  2087.     else if (eai->data_reg == -1) {
  2088.     if (eai->address_reg == -2)
  2089.         /* Constant address */
  2090.         assemble_long(address_space + (uae_s32)eai->addr_const_off);
  2091.     else if (eai->address_reg == -1) {
  2092.         /* Register in its home location */
  2093.         if (eai->mode == Areg)
  2094.         assemble_long(regs.regs + 8  + eai->reg);
  2095.         else
  2096.         assemble_long(regs.regs + eai->reg);
  2097.     } else {
  2098. #if 0
  2099.         /* Indirect address with offset */
  2100.         if ((uae_s32)eai->addr_const_off >= -128 && (uae_s32)eai->addr_const_off <= 127) {
  2101.         }
  2102. #endif
  2103.         assemble_long(address_space + (uae_s32)eai->addr_const_off);
  2104.     }
  2105.     }
  2106. }
  2107.  
  2108. static void compile_eas(struct register_mapping *map, struct ea_info *eainf, int eaino_s, int eaino_d, 
  2109.             int optype)
  2110. {
  2111.     struct ea_info *eais = eainf + eaino_s;
  2112.     struct ea_info *eaid = eainf + eaino_d;
  2113.     int szflag = eais->size == sz_byte ? 0 : 1;
  2114.     int swapflag = 0;
  2115.     int opcode;
  2116.  
  2117.     if (eais->data_reg == -1) {
  2118.     compile_force_byteorder(map, eais->address_reg, BO_NORMAL, 0);
  2119.     eais = eainf + eaino_d;
  2120.     eaid = eainf + eaino_s;
  2121.     swapflag = 1;
  2122.     }
  2123.     if (eais->data_reg == -1) {
  2124.     compile_force_byteorder(map, eais->address_reg, BO_NORMAL, 0);
  2125.     }
  2126.  
  2127.     if (eais->size == sz_word)
  2128.     assemble(0x66);
  2129.  
  2130.     if (eais->data_reg == -2) {
  2131.     assemble(0x80+szflag);
  2132.     assemble(8*optype | rmop_long(eaid));
  2133.     rmop_finalize(eaid);
  2134.     switch(eais->size) {
  2135.      case sz_byte: assemble(eais->data_const_off); break;
  2136.      case sz_word: assemble_uword(eais->data_const_off); break;
  2137.      case sz_long: assemble_ulong(eais->data_const_off); break;
  2138.     }
  2139.     } else {
  2140.     assemble(8*optype | szflag | 2*swapflag);
  2141.     assemble(rmop_long(eaid) | rmop_short(eais));
  2142.     rmop_finalize(eaid);
  2143.     }
  2144. }
  2145.  
  2146. static void compile_fetchmem(struct register_mapping *map, struct ea_info *eai)
  2147. {
  2148.     int x86r;
  2149.     if (eai->size == sz_byte)
  2150.     x86r = get_typed_x86_register(map, DATA_X86_REGS);
  2151.     else
  2152.     x86r = get_free_x86_register(map, ALL_X86_REGS);
  2153.  
  2154.     lock_reg(map, x86r, 2);
  2155.     compile_force_byteorder(map, eai->address_reg, BO_NORMAL, 0);
  2156.     compile_move_reg_from_mem_regoffs(x86r, eai->address_reg, 
  2157.                       (uae_u32)(eai->addr_const_off + address_space),
  2158.                       eai->size);
  2159.     map->x86_verified[x86r] = 0;
  2160.     switch (eai->size) {
  2161.      case sz_byte: map->x86_byteorder[x86r] = BO_NORMAL; break;
  2162.      case sz_word: map->x86_byteorder[x86r] = BO_SWAPPED_WORD; break;
  2163.      case sz_long: map->x86_byteorder[x86r] = BO_SWAPPED_LONG; break;
  2164.     }
  2165.     eai->data_reg = x86r;
  2166.     eai->data_const_off = 0;
  2167. }
  2168.  
  2169. static void compile_fetchimm(struct register_mapping *map, struct ea_info *eai, int byteorder)
  2170. {
  2171.     int x86r;
  2172.     if (eai->size == sz_byte)
  2173.     x86r = get_typed_x86_register(map, DATA_X86_REGS);
  2174.     else
  2175.     x86r = get_free_x86_register(map, ALL_X86_REGS);
  2176.  
  2177.     switch (byteorder) {
  2178.      case BO_SWAPPED_LONG:
  2179.     eai->data_const_off = (((eai->data_const_off & 0xFF000000) >> 24)
  2180.                    | ((eai->data_const_off & 0xFF0000) >> 8)
  2181.                    | ((eai->data_const_off & 0xFF00) << 8)
  2182.                    | ((eai->data_const_off & 0xFF) << 24));
  2183.     break;
  2184.      case BO_SWAPPED_WORD:
  2185.     eai->data_const_off = (((eai->data_const_off & 0xFF00) >> 8)
  2186.                    | ((eai->data_const_off & 0xFF) << 8)
  2187.                    | (eai->data_const_off & 0xFFFF0000));
  2188.     break;
  2189.      case BO_NORMAL:
  2190.     break;
  2191.     }
  2192.     lock_reg(map, x86r, 2);
  2193.     map->x86_byteorder[x86r] = byteorder; map->x86_verified[x86r] = 0;
  2194.  
  2195.     switch (eai->size) {
  2196.      case sz_byte: assemble(0xC6); assemble(0xC0 + x86r); assemble(eai->data_const_off); break;
  2197.      case sz_word: assemble(0x66); assemble(0xC7); assemble(0xC0 + x86r); assemble_uword(eai->data_const_off); break;
  2198.      case sz_long: assemble(0xC7); assemble(0xC0 + x86r); assemble_ulong(eai->data_const_off); break;
  2199.     }
  2200.     eai->data_reg = x86r;
  2201.     eai->data_const_off = 0;
  2202. }
  2203.  
  2204. /*
  2205.  * 1: reg
  2206.  * 2: mem
  2207.  * 4: imm
  2208.  */
  2209.  
  2210. static int binop_alternatives[] = {
  2211.     7, 1,
  2212.     5, 3,
  2213.     0, 0
  2214. };    
  2215.  
  2216. static int binop_worda_alternatives[] = {
  2217.     1, 3,
  2218.     0, 0
  2219. };    
  2220.  
  2221. static int regonly_alternatives[] = {
  2222.     1, 1,
  2223.     0, 0
  2224. };    
  2225.  
  2226. static void compile_loadeas(struct register_mapping *map, struct ea_info *eainf,
  2227.                int eaino_s, int eaino_d, int *alternatives,
  2228.                int scramble_poss, int load_dest)
  2229. {
  2230.     struct ea_info *eais = eainf + eaino_s;
  2231.     struct ea_info *eaid = eainf + eaino_d;
  2232.     int scrambled_bo = eaid->size == sz_long ? BO_SWAPPED_LONG : eaid->size == sz_word ? BO_SWAPPED_WORD : BO_NORMAL;
  2233.     int i, scrambled = 0;
  2234.     int best = 0;
  2235.     int bestcost = -1;
  2236.     int *ap;
  2237.     uae_u32 *sregp = NULL, *dregp = NULL;
  2238.     int screg = -1, dcreg = -1;
  2239.     int stype = -1, dtype = -1;
  2240.     int asrc, adst;
  2241.     int regprefs = eais->size == sz_byte ? DATA_X86_REGS : 0;
  2242.  
  2243.     if (eais->mode == Dreg) {
  2244.     stype = 0;
  2245.     screg = map->dreg_map[eais->reg];
  2246.     if (screg == -1)
  2247.         sregp = regs.regs + eais->reg;
  2248.     } else if (eais->mode == Areg) {
  2249.     stype = 0;
  2250.     screg = map->areg_map[eais->reg];
  2251.     if (screg == -1)
  2252.         sregp = regs.regs + 8 + eais->reg;
  2253.     } else if (eais->data_reg == -2) {
  2254.     stype = -2;
  2255.     }
  2256.  
  2257.     if (eaid->mode == Dreg) {
  2258.     dtype = 0;
  2259.     dcreg = map->dreg_map[eaid->reg];
  2260.     if (dcreg == -1)
  2261.         dregp = regs.regs + eaid->reg;
  2262.     } else if (eaid->mode == Areg) {
  2263.     dtype = 0;
  2264.     dcreg = map->areg_map[eaid->reg];
  2265.     if (dcreg == -1)
  2266.         dregp = regs.regs + 8 + eaid->reg;
  2267.     } else if (eaid->data_reg == -2) {
  2268.     dtype = -2;
  2269.     }
  2270.  
  2271.     ap = alternatives;
  2272.     
  2273.     for (i = 0;; i++) {
  2274.     int cost = 0;
  2275.  
  2276.     asrc = *ap++;
  2277.     if (asrc == 0)
  2278.         break;
  2279.     adst = *ap++;
  2280.     
  2281.     if (stype == -2 && (asrc & 4) == 0)
  2282.         cost++;
  2283.     else if (stype == -1 && ((asrc & 2) == 0 || (eais->size != sz_byte && !scramble_poss)))
  2284.         cost++;
  2285.     else if (stype == 0 && screg == -1 && (asrc & 2) == 0)
  2286.         cost++;
  2287.     
  2288.     if (dtype == -1 && ((adst & 2) == 0 || (eaid->size != sz_byte && !scramble_poss)))
  2289.         /* The !load_dest case isn't handled by the current code,
  2290.          * and it isn't desirable anyway. Use a different alternative
  2291.          */
  2292.         cost += load_dest ? 1 : 100;
  2293.     else if (dtype == 0 && dcreg == -1 && (adst & 2) == 0)
  2294.         cost++;
  2295.     
  2296.     if (bestcost == -1 || cost < bestcost) {
  2297.         bestcost = cost;
  2298.         best = i;
  2299.     }
  2300.     }
  2301.     
  2302.     asrc = alternatives[2*best];
  2303.     adst = alternatives[2*best+1];
  2304.     
  2305.     if (dtype == -1) {
  2306.     if (load_dest) {
  2307.         if ((adst & 2) == 0 || (eaid->size != sz_byte && !scramble_poss))
  2308.         compile_fetchmem(map, eaid);
  2309.     } else {
  2310.         if ((adst & 2) == 0) {
  2311.         printf("Not loading memory operand. Prepare to die.\n");
  2312.         if (eaid->size == sz_byte)
  2313.             eaid->data_reg = get_typed_x86_register(map, DATA_X86_REGS);
  2314.         else
  2315.             eaid->data_reg = get_free_x86_register(map, ALL_X86_REGS);
  2316.         }
  2317.     }
  2318.     /* Scrambled in both mem and reg cases */
  2319.     if (eaid->size != sz_byte && scramble_poss)
  2320.         scrambled = 1;
  2321.     } else {
  2322.     if (dcreg == -1 && !load_dest && (adst & 2) == 0 && eaid->size == sz_long) {
  2323.         /* We need a register, but we don't need to fetch the old data.
  2324.          * See storeea for some more code handling this case. This first
  2325.          * if statement could be eliminated, we would generate some
  2326.          * superfluous moves. This is an optimization. If it were not
  2327.          * done, the mem-mem-move warning could be commented in in
  2328.          * storeea. */
  2329.         if (eaid->size == sz_byte)
  2330.         eaid->data_reg = get_typed_x86_register(map, DATA_X86_REGS);
  2331.         else
  2332.         eaid->data_reg = get_free_x86_register(map, ALL_X86_REGS);
  2333.         eaid->data_const_off = 0;
  2334.     } else if ((dcreg == -1 && (adst & 2) == 0) || dcreg != -1) {
  2335.         int reg_bo;
  2336.         eaid->data_reg = get_and_lock_68k_reg(map, eaid->reg, eaid->mode == Dreg, regprefs, 1, 2);
  2337.         eaid->data_const_off = 0;
  2338.         
  2339.         reg_bo = map->x86_byteorder[eaid->data_reg];
  2340.     
  2341.         if (reg_bo != BO_NORMAL) {
  2342.         if (reg_bo != scrambled_bo)
  2343.             compile_force_byteorder(map, eaid->data_reg, BO_NORMAL, 0);
  2344.         else if (scramble_poss)
  2345.             scrambled = 1;
  2346.         }
  2347.     }
  2348.     }
  2349.     
  2350.     if (stype == -2) {
  2351.     /* @@@ may need to scramble imm, this is a workaround */
  2352.     if ((asrc & 4) == 0 || scrambled)
  2353.         compile_fetchimm(map, eais, scrambled ? scrambled_bo : BO_NORMAL);
  2354.     } else if (stype == -1) {
  2355.     if ((asrc & 2) == 0 || (eais->size != sz_byte && !scrambled))
  2356.         compile_fetchmem(map, eais);
  2357.     } else {
  2358.     if ((screg == -1 && (asrc & 2) == 0) || screg != -1) {
  2359.         eais->data_reg = get_and_lock_68k_reg(map, eais->reg, eais->mode == Dreg, regprefs, 1, 2);
  2360.         eais->data_const_off = 0;
  2361.     }
  2362.     }
  2363.     
  2364.     /* Optimization */
  2365.     if (scrambled && eais->data_reg >= 0 && !load_dest
  2366.     && map->x86_byteorder[eais->data_reg] == BO_NORMAL
  2367.     && eaid->size == sz_long && dtype == 0)
  2368.     scrambled = 0;
  2369.     
  2370.     if (regprefs != 0 && eais->data_reg >= 0 && ((1 << eais->data_reg) & regprefs) == 0) {
  2371.     int tmpr = get_typed_x86_register(map, regprefs);
  2372.     compile_move_reg_reg(tmpr, eais->data_reg, sz_long);
  2373.     eais->data_reg = tmpr;
  2374.     }
  2375.     
  2376.     if (regprefs != 0 && eaid->data_reg >= 0 && ((1 << eaid->data_reg) & regprefs) == 0) {
  2377.     int tmpr = get_typed_x86_register(map, regprefs);
  2378.     compile_move_reg_reg(tmpr, eaid->data_reg, sz_long);
  2379.     eaid->data_reg = tmpr;
  2380.     }
  2381.     
  2382.     /* Now set the byteorder once and for all (should already be correct for
  2383.      * most cases) */
  2384.     if (scrambled) {
  2385.     if (eaid->data_reg >= 0)
  2386.         compile_force_byteorder(map, eaid->data_reg, scrambled_bo, 0);
  2387.     if (eais->data_reg >= 0)
  2388.         compile_force_byteorder(map, eais->data_reg, scrambled_bo, 0);    
  2389.     } else {
  2390.     if (eaid->data_reg >= 0)
  2391.         compile_force_byteorder(map, eaid->data_reg, BO_NORMAL, 0);
  2392.     if (eais->data_reg >= 0)
  2393.         compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 0);
  2394.     }
  2395. }
  2396.  
  2397. static void compile_fetchea(struct register_mapping *map, struct ea_info *eainf,
  2398.                 int eaino, int asrc)
  2399. {
  2400.     struct ea_info *eais = eainf + eaino;
  2401.     int scrambled_bo = eais->size == sz_long ? BO_SWAPPED_LONG : eais->size == sz_word ? BO_SWAPPED_WORD : BO_NORMAL;
  2402.     int i, scrambled = 0;
  2403.     int best = 0;
  2404.     int bestcost = -1;
  2405.     int *ap;
  2406.     uae_u32 *sregp = NULL;
  2407.     int screg = -1, stype = -1;
  2408.     int regprefs = eais->size == sz_byte ? DATA_X86_REGS : 0;
  2409.  
  2410.     if (eais->mode == Dreg) {
  2411.     stype = 0;
  2412.     screg = map->dreg_map[eais->reg];
  2413.     if (screg == -1)
  2414.         sregp = regs.regs + eais->reg;
  2415.     } else if (eais->mode == Areg) {
  2416.     stype = 0;
  2417.     screg = map->areg_map[eais->reg];
  2418.     if (screg == -1)
  2419.         sregp = regs.regs + 8 + eais->reg;
  2420.     } else if (eais->data_reg == -2) {
  2421.     stype = -2;
  2422.     }
  2423.  
  2424.     if (stype == -2) {
  2425.     if ((asrc & 4) == 0)
  2426.         compile_fetchimm(map, eais, scrambled ? scrambled_bo : BO_NORMAL);
  2427.     } else if (stype == -1) {
  2428.     if ((asrc & 2) == 0 || eais->size != sz_byte)
  2429.         compile_fetchmem(map, eais);
  2430.     } else {
  2431.     if ((screg == -1 && (asrc & 2) == 0) || screg != -1) {
  2432.         eais->data_reg = get_and_lock_68k_reg(map, eais->reg, eais->mode == Dreg, regprefs, 1, 2);
  2433.         eais->data_const_off = 0;
  2434.     }
  2435.     }
  2436.     
  2437.     if (eais->data_reg >= 0)
  2438.     compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 0);
  2439. }
  2440.  
  2441. /*
  2442.  * compile_note_modify() should be called on destination EAs obtained from
  2443.  * compile_loadeas(), if their value was modified (e.g. by the compile_eas()
  2444.  * function)
  2445.  */
  2446.  
  2447. static void compile_note_modify(struct register_mapping *map, struct ea_info *eainf,
  2448.                 int eaino)
  2449. {
  2450.     struct ea_info *eai = eainf + eaino;
  2451.     int newr;
  2452.     int szflag = eai->size == sz_byte ? 0 : 1;
  2453.  
  2454.     if (eai->mode == Dreg) {
  2455.     /* We only need to do something if we have the value in a register,
  2456.      * otherwise, the home location was modified already */
  2457.     if (eai->data_reg >= 0) {
  2458.         if (eai->data_reg != map->dreg_map[eai->reg]) {
  2459.         remove_x86r_from_cache(map, eai->data_reg, 0);
  2460.         if (map->dreg_map[eai->reg] >= 0)
  2461.             remove_x86r_from_cache(map, map->dreg_map[eai->reg], 0);
  2462.         map->x86_cache_reg[eai->data_reg] = eai->reg;
  2463.         map->x86_cr_type[eai->data_reg] = 1;
  2464.         map->dreg_map[eai->reg] = eai->data_reg;
  2465.         }
  2466.         map->x86_verified[eai->data_reg] = 0;        
  2467.         map->x86_const_offset[eai->data_reg] = eai->data_const_off;
  2468.         map->x86_dirty[eai->data_reg] = 1;
  2469.     }
  2470.     return;
  2471.     } else if (eai->mode == Areg) {
  2472.     if (eai->size != sz_long)
  2473.         printf("Areg put != long\n");
  2474.  
  2475.     /* We only need to do something if we have the value in a register,
  2476.      * otherwise, the home location was modified already */
  2477.     if (eai->data_reg >= 0) {
  2478.         if (eai->data_reg != map->areg_map[eai->reg]) {
  2479.         remove_x86r_from_cache(map, eai->data_reg, 0);
  2480.         if (map->areg_map[eai->reg] >= 0)
  2481.             remove_x86r_from_cache(map, map->areg_map[eai->reg], 0);
  2482.         map->x86_cache_reg[eai->data_reg] = eai->reg;
  2483.         map->x86_cr_type[eai->data_reg] = 0;
  2484.         map->areg_map[eai->reg] = eai->data_reg;
  2485.         }
  2486.         map->x86_verified[eai->data_reg] = 0;        
  2487.         map->x86_const_offset[eai->data_reg] = eai->data_const_off;
  2488.         map->x86_dirty[eai->data_reg] = 1;
  2489.     }
  2490.     return;
  2491.     } else {
  2492.     /* Storing to memory from reg? */
  2493.     if (eai->data_reg >= 0) {
  2494.         compile_offset_reg(map, eai->data_reg, eai->data_const_off);
  2495.     
  2496.         switch (eai->size) {
  2497.          case sz_byte: compile_force_byteorder(map, eai->data_reg, BO_NORMAL, 1); break;
  2498.          case sz_word: compile_force_byteorder(map, eai->data_reg, BO_SWAPPED_WORD, 1); break;
  2499.          case sz_long: compile_force_byteorder(map, eai->data_reg, BO_SWAPPED_LONG, 1); break;
  2500.         }
  2501.         compile_force_byteorder(map, eai->address_reg, BO_NORMAL, 0);
  2502.         compile_move_reg_to_mem_regoffs(eai->address_reg,
  2503.                         (uae_u32)(eai->addr_const_off + address_space),
  2504.                         eai->data_reg, eai->size);
  2505.     }
  2506.     }
  2507. }
  2508.  
  2509. static void compile_storeea(struct register_mapping *map, struct ea_info *eainf,
  2510.                 int eaino_s, int eaino_d)
  2511. {
  2512.     struct ea_info *eais = eainf + eaino_s;
  2513.     struct ea_info *eaid = eainf + eaino_d;
  2514.     int newr, cacher;
  2515.     int szflag = eaid->size == sz_byte ? 0 : 1;
  2516.  
  2517.     if (eaid->mode == Dreg) {
  2518.     /* Is the reg to move from already the register cache reg for the
  2519.      * destination? */
  2520.     if (eais->data_reg >= 0 && eais->data_reg == map->dreg_map[eaid->reg]) {
  2521.         map->x86_dirty[eais->data_reg] = 1; map->x86_verified[eais->data_reg] = 0;
  2522.         map->x86_const_offset[eais->data_reg] = eais->data_const_off;
  2523.         return;
  2524.     }
  2525.     /* Is the destination register in its home location? */
  2526.     if (map->dreg_map[eaid->reg] < 0) {
  2527.         if (eais->data_reg == -2) {
  2528.         /* Move immediate to regs.regs */
  2529.         if (eaid->size == sz_word) assemble(0x66);
  2530.         assemble(0xC6 + szflag); assemble(0x05); assemble_long(regs.regs + eaid->reg);
  2531.         switch (eaid->size) {
  2532.          case sz_byte: assemble(eais->data_const_off); break;
  2533.          case sz_word: assemble_uword(eais->data_const_off); break;
  2534.          case sz_long: assemble_ulong(eais->data_const_off); break;
  2535.         }
  2536.         } else if (eais->data_reg == -1) {
  2537. #if 0
  2538.         printf("Shouldn't happen (mem-mem-move)\n");
  2539. #endif
  2540.         /* This _can_ happen: move.l $4,d0, if d0 isn't in the
  2541.          * cache, will come here. But a reg will be allocated for
  2542.          * dest. We use this. This _really_ shouldn't happen if
  2543.          * the size isn't long. */
  2544.         if (eaid->size != sz_long)
  2545.             printf("_Really_ shouldn't happen (Dreg case)\n");
  2546.         map->x86_cache_reg[eaid->data_reg] = eaid->reg;
  2547.         map->x86_cr_type[eaid->data_reg] = 1;
  2548.         map->x86_const_offset[eaid->data_reg] = eaid->data_const_off;
  2549.         map->dreg_map[eaid->reg] = eaid->data_reg;
  2550.         map->x86_verified[eaid->data_reg] = 0;
  2551.         goto have_cache_reg_d;
  2552.         } else {
  2553.         if (eais->size == sz_long) {
  2554.             /* Make this the new register cache reg */
  2555.             remove_x86r_from_cache(map, eais->data_reg, 0);
  2556.             map->x86_cache_reg[eais->data_reg] = eaid->reg;
  2557.             map->x86_cr_type[eais->data_reg] = 1;
  2558.             map->x86_const_offset[eais->data_reg] = eais->data_const_off;
  2559.             map->dreg_map[eaid->reg] = eais->data_reg;
  2560.             map->x86_verified[eais->data_reg] = 0;
  2561.         } else {
  2562.             /* Move from reg to regs.regs */
  2563.             compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 1);
  2564.             compile_offset_reg (map, eais->data_reg, eais->data_const_off);
  2565.             if (eaid->size == sz_word) assemble(0x66);
  2566.             assemble(0x88 + szflag); assemble(0x05 + 8*eais->data_reg);
  2567.             assemble_long(regs.regs + eaid->reg);
  2568.         }
  2569.         }
  2570.     } else {
  2571.         int destr;
  2572.         
  2573.         have_cache_reg_d:
  2574.  
  2575.         destr = map->dreg_map[eaid->reg];
  2576.         if (eaid->size != sz_long)
  2577.         compile_force_byteorder(map, destr, BO_NORMAL, 1);
  2578.  
  2579.         if (eais->data_reg == -2) {
  2580.         /* Move immediate to reg */
  2581.         if (eaid->size == sz_word) assemble(0x66);
  2582.         assemble(0xC6 + szflag); assemble(0xC0 + destr);
  2583.         switch (eaid->size) {
  2584.          case sz_byte: assemble(eais->data_const_off); break;
  2585.          case sz_word: assemble_uword(eais->data_const_off); break;
  2586.          case sz_long: assemble_ulong(eais->data_const_off); break;
  2587.         }
  2588.         /* normal byteorder comes either from force above or from long
  2589.          * const move */
  2590.         map->x86_byteorder[destr] = BO_NORMAL;
  2591.         } else if (eais->data_reg == -1) {
  2592.         if (eais->mode == Dreg) {
  2593.             compile_move_reg_from_mem_regoffs(destr, -2, (uae_u32)(regs.regs + eais->reg),
  2594.                               eais->size);
  2595.             map->x86_byteorder[destr] = BO_NORMAL;
  2596.         } else if (eais->mode == Areg) {
  2597.             compile_move_reg_from_mem_regoffs(destr, -2, (uae_u32)(regs.regs + 8 + eais->reg),
  2598.                               eais->size);
  2599.             map->x86_byteorder[destr] = BO_NORMAL;
  2600.         } else {
  2601.             /* Move mem to reg */
  2602.             compile_force_byteorder(map, eais->address_reg, BO_NORMAL, 0);
  2603.             compile_move_reg_from_mem_regoffs(destr, eais->address_reg,
  2604.                               (uae_u32)(eais->addr_const_off + address_space),
  2605.                               eais->size);
  2606.  
  2607.             switch (eais->size) {
  2608.              case sz_byte: map->x86_byteorder[destr] = BO_NORMAL; break;
  2609.              case sz_word: map->x86_byteorder[destr] = BO_SWAPPED_WORD; break;
  2610.              case sz_long: map->x86_byteorder[destr] = BO_SWAPPED_LONG; break;
  2611.             }
  2612.         }
  2613.         } else {
  2614.         if (eais->size == sz_long) {
  2615.             /* Make this the new register cache reg */
  2616.             remove_x86r_from_cache(map, eais->data_reg, 0);
  2617.             remove_x86r_from_cache(map, destr, 0);
  2618.             map->x86_cache_reg[eais->data_reg] = eaid->reg;
  2619.             map->x86_cr_type[eais->data_reg] = 1;
  2620.             map->x86_const_offset[eais->data_reg] = eais->data_const_off;
  2621.             map->dreg_map[eaid->reg] = eais->data_reg;
  2622.             map->x86_verified[eais->data_reg] = 0;
  2623.         } else {
  2624.             /* Move from reg to reg */
  2625.             compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 1);
  2626.             compile_offset_reg (map, eais->data_reg, eais->data_const_off);
  2627.             if (eaid->size == sz_word) assemble(0x66);
  2628.             assemble(0x88 + szflag); assemble(0xC0 + destr + 8*eais->data_reg);
  2629.         }
  2630.         }
  2631.     }
  2632.     
  2633.     if (map->dreg_map[eaid->reg] >= 0)
  2634.         map->x86_dirty[map->dreg_map[eaid->reg]] = 1;
  2635.     return;
  2636.     } else if (eaid->mode == Areg) {
  2637.     if (eaid->size != sz_long)
  2638.         printf("Areg put != long\n");
  2639.  
  2640.     /* Is the reg to move from already the register cache reg for the
  2641.      * destination? */
  2642.     if (eais->data_reg >= 0 && eais->data_reg == map->areg_map[eaid->reg]) {
  2643.         map->x86_dirty[eais->data_reg] = 1; map->x86_verified[eais->data_reg] = 0;
  2644.         map->x86_const_offset[eais->data_reg] = eais->data_const_off;
  2645.         return;
  2646.     }    
  2647.     /* Is the destination register in its home location? */
  2648.     if (map->areg_map[eaid->reg] < 0) {
  2649.         if (eais->data_reg == -2) {
  2650.         /* Move immediate to regs.regs */
  2651.         assemble(0xC7); assemble(0x05); assemble_long(regs.regs + 8 + eaid->reg);
  2652.         assemble_ulong(eais->data_const_off);
  2653.         } else if (eais->data_reg == -1) {
  2654. #if 0 /* see above... */
  2655.         printf("Shouldn't happen (mem-mem-move)\n");
  2656. #endif
  2657.         map->x86_cache_reg[eaid->data_reg] = eaid->reg;
  2658.         map->x86_cr_type[eaid->data_reg] = 0;
  2659.         map->x86_const_offset[eaid->data_reg] = eaid->data_const_off;
  2660.         map->areg_map[eaid->reg] = eaid->data_reg;
  2661.         map->x86_verified[eaid->data_reg] = 0;
  2662.         goto have_cache_reg_a;
  2663.         } else {
  2664.         /* Make this the new register cache reg */
  2665.         remove_x86r_from_cache(map, eais->data_reg, 0);
  2666.         map->x86_cache_reg[eais->data_reg] = eaid->reg;
  2667.         map->x86_cr_type[eais->data_reg] = 0;
  2668.         map->x86_const_offset[eais->data_reg] = eais->data_const_off;
  2669.         map->areg_map[eaid->reg] = eais->data_reg;
  2670.         map->x86_verified[eais->data_reg] = 0;
  2671.         }
  2672.     } else {
  2673.         int destr;
  2674.         
  2675.         have_cache_reg_a:
  2676.  
  2677.         destr = map->areg_map[eaid->reg];
  2678.         if (eaid->size != sz_long)
  2679.         compile_force_byteorder(map, destr, BO_NORMAL, 1);
  2680.  
  2681.         if (eais->data_reg == -2) {
  2682.         /* Move immediate to reg */
  2683.         assemble(0xC7); assemble(0xC0 + destr);
  2684.         assemble_ulong(eais->data_const_off);
  2685.  
  2686.         /* normal byteorder comes either from force above or from long
  2687.          * const move */
  2688.         map->x86_byteorder[destr] = BO_NORMAL;
  2689.         } else if (eais->data_reg == -1) {
  2690.         if (eais->mode == Dreg) {
  2691.             compile_move_reg_from_mem_regoffs(destr, -2, (uae_u32)(regs.regs + eais->reg),
  2692.                               eais->size);
  2693.             map->x86_byteorder[destr] = BO_NORMAL;
  2694.         } else if (eais->mode == Areg) {
  2695.             compile_move_reg_from_mem_regoffs(destr, -2, (uae_u32)(regs.regs + 8 + eais->reg),
  2696.                               eais->size);
  2697.             map->x86_byteorder[destr] = BO_NORMAL;
  2698.         } else {
  2699.             /* Move mem to reg */
  2700.             compile_force_byteorder(map, eais->address_reg, BO_NORMAL, 0);
  2701.             compile_move_reg_from_mem_regoffs(destr, eais->address_reg, 
  2702.                               (uae_u32)(eais->addr_const_off + address_space),
  2703.                               eais->size);
  2704.     
  2705.             map->x86_byteorder[destr] = BO_SWAPPED_LONG;
  2706.         }
  2707.         } else {
  2708.         /* Make this the new register cache reg */
  2709.         remove_x86r_from_cache(map, eais->data_reg, 0);
  2710.         remove_x86r_from_cache(map, destr, 0);
  2711.         map->x86_cache_reg[eais->data_reg] = eaid->reg;
  2712.         map->x86_cr_type[eais->data_reg] = 0;
  2713.         map->x86_const_offset[eais->data_reg] = eais->data_const_off;
  2714.         map->areg_map[eaid->reg] = eais->data_reg;
  2715.         map->x86_verified[eais->data_reg] = 0;
  2716.         }
  2717.     }
  2718.     
  2719.     if (map->areg_map[eaid->reg] >= 0)
  2720.         map->x86_dirty[map->areg_map[eaid->reg]] = 1;
  2721.     return;
  2722.     }
  2723.  
  2724.     if (eais->data_reg == -1)
  2725.     printf("Storing to mem, but not from reg\n");
  2726.     /* Correct the byteorder */
  2727.     if (eais->data_reg != -2) {
  2728.     compile_offset_reg(map, eais->data_reg, eais->data_const_off);
  2729.     
  2730.     switch (eaid->size) {
  2731.      case sz_byte: compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 1); break;
  2732.      case sz_word: compile_force_byteorder(map, eais->data_reg, BO_SWAPPED_WORD, 1); break;
  2733.      case sz_long: compile_force_byteorder(map, eais->data_reg, BO_SWAPPED_LONG, 1); break;
  2734.     }
  2735.     compile_force_byteorder(map, eaid->address_reg, BO_NORMAL, 0);
  2736.     compile_move_reg_to_mem_regoffs(eaid->address_reg,
  2737.                     (uae_u32)(eaid->addr_const_off + address_space),
  2738.                     eais->data_reg, eaid->size);
  2739.     } else {
  2740.     switch (eaid->size) {
  2741.      case sz_long:
  2742.         eais->data_const_off = (((eais->data_const_off & 0xFF000000) >> 24)
  2743.                  | ((eais->data_const_off & 0xFF0000) >> 8)
  2744.                  | ((eais->data_const_off & 0xFF00) << 8)
  2745.                  | ((eais->data_const_off & 0xFF) << 24));
  2746.         break;
  2747.      case sz_word:
  2748.         eais->data_const_off = (((eais->data_const_off & 0xFF00) >> 8)
  2749.                  | ((eais->data_const_off & 0xFF) << 8));
  2750.         break;
  2751.     }
  2752.     compile_force_byteorder(map, eaid->address_reg, BO_NORMAL, 0);
  2753.     /* generate code to move valueoffset,eaoffset(eareg) */
  2754.     switch(eaid->size) {                   
  2755.      case sz_byte: assemble(0xC6); break;
  2756.      case sz_word: assemble(0x66); /* fall through */
  2757.      case sz_long: assemble(0xC7); break;
  2758.     }
  2759.     if (eaid->address_reg == -2) { /* absolute or PC-relative */
  2760.         assemble(0x05);
  2761.         assemble_long(eaid->addr_const_off + address_space);
  2762.     } else {
  2763.         assemble(0x80 + eaid->address_reg);
  2764.         assemble_long(eaid->addr_const_off + address_space);
  2765.     }
  2766.     switch(eaid->size) {
  2767.      case sz_byte: assemble(eais->data_const_off); break;
  2768.      case sz_word: assemble_uword(eais->data_const_off); break;
  2769.      case sz_long: assemble_ulong(eais->data_const_off); break;
  2770.     }
  2771.     }
  2772. }
  2773.  
  2774. #define CE_STACK_SIZE 1000
  2775.  
  2776. static struct {
  2777.     struct register_mapping map;
  2778.     char *jmpoffs;
  2779.     uae_u32 address;
  2780.     int noflush:1;
  2781. } compile_exit_stack[CE_STACK_SIZE];
  2782.  
  2783. static int cesp;
  2784.  
  2785. static struct register_mapping current_exit_regmap;
  2786.  
  2787. static void generate_exit(struct register_mapping *map, int address)
  2788. {
  2789.     int i;
  2790.     
  2791.     if (map != NULL)
  2792.     sync_reg_cache (map, 1);
  2793.     assemble(0xB8); /* movl $new_pc,%eax */
  2794.     assemble_ulong(address);
  2795.     assemble(0xC3); /* RET */
  2796. }
  2797.  
  2798. static void copy_map_with_undo(struct register_mapping *dst, 
  2799.                    struct register_mapping *src,
  2800.                    struct pid_undo *pud)
  2801. {
  2802.     int i;
  2803.     *dst = *src;
  2804.     for (i = 0; i < pud->used; i++) {
  2805.     int m68kr = pud->m68kr[i];
  2806.     int x86r = pud->x86r[i];
  2807.     int old_cr = dst->areg_map[m68kr];
  2808.     if (old_cr != -1) {
  2809.         dst->x86_cache_reg[old_cr] = -1;
  2810.     }
  2811.     dst->x86_cache_reg[x86r] = m68kr;
  2812.     dst->areg_map[m68kr] = x86r;
  2813.     dst->x86_cr_type[x86r] = 0;
  2814.     dst->x86_const_offset[x86r] = pud->offs[i];
  2815.     dst->x86_dirty[x86r] = pud->dirty[i];
  2816.     }
  2817. }
  2818.  
  2819. static void unlock_pud(struct register_mapping *map, struct pid_undo *pud)
  2820. {
  2821.     int i;
  2822.     for (i = 0; i < pud->used; i++) {
  2823.     compile_unlock_reg(map, pud->x86r[i]);
  2824.     }
  2825. }
  2826.  
  2827. static int exits_necessary;
  2828.  
  2829. static void generate_possible_exit(struct register_mapping *map,
  2830.                    struct ea_info *eai, int iip,
  2831.                    struct pid_undo *pud)
  2832. {
  2833.     struct register_mapping exit_regmap;
  2834.     
  2835.     if (!exits_necessary) {
  2836.     unlock_pud(map, pud);
  2837.     return;
  2838.     }
  2839.  
  2840.     compile_force_byteorder(map, eai->address_reg, BO_NORMAL, 0);
  2841.     switch (eai->address_reg) {
  2842.      case -1:
  2843.     /* EA doesn't refer to memory */
  2844.     break;
  2845.      case -2:
  2846.     /* Only a constant offset */
  2847.     eai->addr_const_off &= (1<<24)-1;
  2848.     if (!good_address_map[eai->addr_const_off]) {
  2849.         copy_map_with_undo(&exit_regmap, map, pud);
  2850.         generate_exit(&exit_regmap, insn_info[iip].address);
  2851.     }
  2852.     break;
  2853.      default:
  2854.     if (map->x86_verified[eai->address_reg])
  2855.         break;
  2856.     map->x86_verified[eai->address_reg] = 1;
  2857.     if (cesp == CE_STACK_SIZE) {
  2858.         copy_map_with_undo(&exit_regmap, map, pud);
  2859.         generate_exit(&exit_regmap, insn_info[iip].address);
  2860.         break;
  2861.     }
  2862.     copy_map_with_undo(&compile_exit_stack[cesp].map, map, pud);
  2863.     compile_exit_stack[cesp].address = insn_info[iip].address;
  2864.     assemble(0x80); assemble(0xB8 + eai->address_reg); /* cmpb $0, good_address_map(x86r) */
  2865.     assemble_long(good_address_map + eai->addr_const_off);
  2866.     assemble(0);
  2867.     assemble(0x0F); assemble(0x84); /* JE finish */
  2868.     compile_exit_stack[cesp].jmpoffs = compile_here();
  2869.     compile_exit_stack[cesp].noflush = 0;
  2870.     assemble_ulong(0);
  2871.     cesp++;
  2872.     break;
  2873.     }
  2874.     unlock_pud(map, pud);
  2875. }
  2876.  
  2877. static void finish_exits(void)
  2878. {
  2879.     int i;
  2880.     for (i = 0; i < cesp; i++) {
  2881.     char *exitpoint = compile_here();
  2882.     char *nextpoint;
  2883.  
  2884.     if (compile_exit_stack[i].noflush)
  2885.         generate_exit(NULL, compile_exit_stack[i].address);
  2886.     else
  2887.         generate_exit(&compile_exit_stack[i].map, compile_exit_stack[i].address);
  2888.     nextpoint = compile_here();
  2889.     compile_org(compile_exit_stack[i].jmpoffs);
  2890.     assemble_ulong(exitpoint - (compile_exit_stack[i].jmpoffs + 4));
  2891.     compile_org(nextpoint);
  2892.     }
  2893. }
  2894.  
  2895. static void finish_condjumps(int lastiip)
  2896. {
  2897.     int iip;
  2898.     char *lastptr = compile_here();
  2899.     for (iip = 0; iip < lastiip; iip++) {
  2900.     char *fillin = insn_info[iip].compiled_fillin;
  2901.     if (fillin != NULL) {
  2902.         compile_org(insn_info[iip].compiled_fillin);
  2903.         assemble_ulong(insn_info[insn_info[iip].jumps_to].compiled_jumpaddr - (fillin + 4));
  2904.     }
  2905.     }
  2906.     compile_org(lastptr);
  2907. }
  2908.  
  2909. #define CC_X_FROM_86C 1
  2910. #define CC_C_FROM_86C 2
  2911. #define CC_Z_FROM_86Z 4
  2912. #define CC_V_FROM_86V 8 
  2913. #define CC_N_FROM_86N 16
  2914. #define CC_TEST_REG   32
  2915. #define CC_Z_FROM_86C 64
  2916. #define CC_SAHF       128
  2917. #define CC_TEST_CONST 256
  2918. #define CC_AFTER_RO   512
  2919. #define CC_AFTER_ROX  1024
  2920.  
  2921. static unsigned int cc_status;
  2922. static int cc_reg;
  2923. static uae_u32 cc_offset;
  2924. static wordsizes cc_size;
  2925.  
  2926. static void compile_do_cc_test_reg(struct register_mapping *map)
  2927. {
  2928.     compile_force_byteorder(map, cc_reg, BO_NORMAL, 1);
  2929.     if (cc_offset != 0)
  2930.     printf("Pull my finger\n");
  2931.     if (cc_size == sz_word) /* test ccreg */
  2932.     assemble(0x66);
  2933.     if (cc_size == sz_byte)
  2934.     assemble(0x84);
  2935.     else
  2936.     assemble(0x85);
  2937.     assemble(0xC0 + 9*cc_reg);
  2938. }
  2939.  
  2940. static int compile_flush_cc_cache(struct register_mapping *map, int status, 
  2941.                   int live_at_end, int user_follows,
  2942.                   int user_live_at_end, int user_ccval)
  2943. {
  2944.     int status_for_user = 0;
  2945.  
  2946.     if (user_follows) {
  2947.     int need_for_user = 0;
  2948.     int user_flagmask = cc_flagmask_68k(user_ccval);
  2949.  
  2950.     if (user_flagmask & CC68K_C)
  2951.         need_for_user |= CC_C_FROM_86C;
  2952.     if (user_flagmask & CC68K_Z)
  2953.         need_for_user |= CC_Z_FROM_86Z;
  2954.     if (user_flagmask & CC68K_N)
  2955.         need_for_user |= CC_N_FROM_86N;
  2956.     if (user_flagmask & CC68K_V)
  2957.         need_for_user |= CC_V_FROM_86V;
  2958.  
  2959.     /* Check whether we can satisfy the user's needs in a simple way. */
  2960.     if ((need_for_user & status) == need_for_user)
  2961.         status_for_user = status;
  2962.     else if (user_flagmask == CC68K_Z && status == CC_Z_FROM_86C)
  2963.         status_for_user = status;
  2964.     else if (status == CC_TEST_REG && (user_flagmask & (CC68K_C|CC68K_V|CC68K_Z|CC68K_N)) != 0) {
  2965.         if (cc_reg == -2) {
  2966.         status_for_user = CC_TEST_CONST;
  2967.         } else {
  2968.         compile_do_cc_test_reg(map);
  2969.         status_for_user = status = (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V);
  2970.         }
  2971.     } else if (status == CC_AFTER_RO) {
  2972.         /* We fake some information here... */
  2973.         if (user_flagmask == CC68K_C && (user_live_at_end & ~CC68K_C) == 0)
  2974.         status = status_for_user = CC_C_FROM_86C;
  2975.         else if (((user_flagmask | user_live_at_end) & (CC68K_C|CC68K_V)) == 0) {
  2976.         status = CC_TEST_REG; user_live_at_end = CC68K_Z|CC68K_N|CC68K_V;
  2977.         status_for_user = (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V);
  2978.         } else
  2979.         status_for_user = CC_SAHF;
  2980.     } else if (status == CC_AFTER_ROX) {
  2981.         if (user_flagmask == CC68K_C && (user_live_at_end & ~(CC68K_C|CC68K_X)) == 0)
  2982.         status = status_for_user = CC_C_FROM_86C;
  2983.         else if (((user_flagmask | user_live_at_end) & (CC68K_C|CC68K_X|CC68K_V)) == 0) {
  2984.         status = CC_TEST_REG; user_live_at_end = CC68K_Z|CC68K_N|CC68K_V;
  2985.         status_for_user = (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V);
  2986.         } else
  2987.         status_for_user = CC_SAHF;
  2988.     } else if (need_for_user != 0) {
  2989.         /* No way to handle it easily */
  2990.         status_for_user = CC_SAHF;
  2991.     }
  2992.     if (status_for_user != CC_SAHF)
  2993.         live_at_end = user_live_at_end;
  2994.     }
  2995.  
  2996.     /*
  2997.      * Now store the flags which are live at the end of this insn and set by 
  2998.      * us into their home locations 
  2999.      */
  3000.     if (status == CC_TEST_REG) {
  3001.     if ((live_at_end & (CC68K_C|CC68K_V|CC68K_Z|CC68K_N)) == 0)
  3002.         goto all_ok;
  3003.  
  3004.     if (cc_reg == -2) {
  3005.         uae_u8 f = 0;
  3006.         if (cc_size == sz_byte) {
  3007.         f |= (cc_offset & 0x80) ? 0x80 : 0;
  3008.         f |= (cc_offset & 0xFF) == 0 ? 0x40 : 0;
  3009.         } else if (cc_size == sz_byte) {
  3010.         f |= (cc_offset & 0x8000) ? 0x80 : 0;
  3011.         f |= (cc_offset & 0xFFFF) == 0 ? 0x40 : 0;
  3012.         } else {
  3013.         f |= (cc_offset & 0x80000000) ? 0x80 : 0;
  3014.         f |= (cc_offset & 0xFFFFFFFF) == 0 ? 0x40 : 0;
  3015.         }
  3016.         assemble(0xC7); assemble(0x05); 
  3017.         assemble_long((char*)®flags);
  3018.         assemble_uword(f);
  3019.     } else {
  3020.         int tmpr = get_free_x86_register(map, ALL_X86_REGS);
  3021.         compile_do_cc_test_reg(map);
  3022.  
  3023.         /* pushfl; popl tmpr; movl tempr, regflags */
  3024.         assemble(0x9C); assemble(0x58+tmpr);
  3025.         compile_move_reg_to_mem_regoffs(-2, (uae_u32)®flags, tmpr, sz_long);
  3026.     }
  3027.     } else if (status == CC_Z_FROM_86C) {
  3028.     if ((live_at_end & CC68K_Z) != 0) {
  3029.         int tmpr = get_typed_x86_register(map, DATA_X86_REGS);
  3030.         assemble(0x9C);
  3031.         /* setnc tmpr; shl $6, tmpr; andb $~0x40, regflags; orb tmpr, regflags */
  3032.         assemble(0x0F); assemble(0x93); assemble(0xC0 + tmpr);
  3033.         assemble(0xC0); assemble(4*8 + 0xC0 + tmpr); assemble(6);
  3034.         assemble(0x80); assemble(0x05+0x20); assemble_long(®flags); assemble((uae_u8)~0x40);
  3035.         assemble(0x08); assemble(0x05+ tmpr*8); assemble_long(®flags);
  3036.         assemble(0x9D);
  3037.     }
  3038.     } else if (status == CC_AFTER_RO || status == CC_AFTER_ROX) {
  3039.     int tmpr = get_typed_x86_register(map, DATA_X86_REGS);
  3040.     assemble(0x9C);
  3041.     compile_do_cc_test_reg(map);
  3042.     /* pushfl; popl tmpr; andl $0xff,tmpr (mask out V flag which is cleared after rotates) */
  3043.     assemble(0x9C); assemble(0x58 + tmpr);
  3044.     assemble(0x81); assemble(0xC0 + tmpr + 8*4); assemble_ulong(0xFF);
  3045.     assemble(0x9D);
  3046.     /* adc $0, tmpr */
  3047.     assemble(0x80); assemble(0xC0 + tmpr + 8*2); assemble(0);
  3048.     compile_move_reg_to_mem_regoffs(-2, (uae_u32)®flags, tmpr, sz_long);
  3049.     if (status == CC_AFTER_ROX)
  3050.         compile_move_reg_to_mem_regoffs(-2, 4 + (uae_u32)®flags, tmpr, sz_long);
  3051.     } else if (status != 0) {
  3052.     assert((status & CC_TEST_REG) == 0);
  3053.     assert (status == (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_X_FROM_86C | CC_V_FROM_86V)
  3054.         || status == (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V)
  3055.         || status == CC_C_FROM_86C);
  3056.         
  3057.     if ((status & CC_X_FROM_86C) == 0)
  3058.         live_at_end &= ~CC68K_X;
  3059.     
  3060.     if (status == CC_C_FROM_86C && (live_at_end & CC68K_C) != 0) 
  3061.         fprintf(stderr, "Shouldn't be needing C here!\n");
  3062.     else if (live_at_end) {
  3063.         if ((live_at_end & CC68K_X) == 0)
  3064.         status &= ~CC_X_FROM_86C;
  3065.  
  3066.         if (live_at_end) {
  3067.         if ((status & CC_X_FROM_86C) != 0 && live_at_end == CC68K_X) {
  3068.             /* SETC regflags + 4 */
  3069.             assemble(0x0F); assemble(0x92);
  3070.             assemble(0x05); assemble_long(4 + (uae_u32)®flags);
  3071.         } else {
  3072.             int tmpr = get_free_x86_register(map, ALL_X86_REGS);
  3073.             /* pushfl; popl tmpr; movl tempr, regflags */
  3074.             assemble(0x9C); assemble(0x58+tmpr);
  3075.             compile_move_reg_to_mem_regoffs(-2, (uae_u32)®flags, tmpr, sz_long);
  3076.         
  3077.             if (status & CC_X_FROM_86C) {
  3078.             compile_move_reg_to_mem_regoffs(-2, 4 + (uae_u32)®flags, tmpr, sz_word);
  3079.             }
  3080.         }
  3081.         }
  3082.     }
  3083.     }
  3084.  
  3085.     all_ok:
  3086.     return status_for_user;
  3087. }
  3088.  
  3089. static char *compile_condbranch(struct register_mapping *map, int iip,
  3090.                 int new_cc_status)
  3091. {
  3092.     int cc = insn_info[iip].dp->cc;
  3093.     int flagsused = cc_flagmask_68k(cc);
  3094.     int flagsneeded = 0;
  3095.     char *undo_pointer = compile_here();
  3096.  
  3097.     if (flagsused & CC68K_C)
  3098.     flagsneeded |= CC_C_FROM_86C;
  3099.     if (flagsused & CC68K_Z)
  3100.     flagsneeded |= CC_Z_FROM_86Z;
  3101.     if (flagsused & CC68K_N)
  3102.     flagsneeded |= CC_N_FROM_86N;
  3103.     if (flagsused & CC68K_V)
  3104.     flagsneeded |= CC_V_FROM_86V;
  3105.  
  3106.     if (flagsneeded == 0)
  3107.     /* Fine */;
  3108.     else if (new_cc_status == CC_SAHF) {
  3109.     int tmpr = get_free_x86_register(map, ALL_X86_REGS);
  3110.     compile_move_reg_from_mem_regoffs(tmpr, -2, (uae_u32)®flags, sz_long);
  3111.     assemble(0x66); assemble(0x50+tmpr); assemble(0x66); assemble(0x9D);
  3112.     new_cc_status = CC_C_FROM_86C|CC_Z_FROM_86Z|CC_N_FROM_86N|CC_V_FROM_86V;
  3113.     } else if (new_cc_status == CC_TEST_CONST) {
  3114.     int n,z;
  3115.     switch(cc_size) {
  3116.      case sz_byte: n = ((uae_s8)cc_offset) < 0; z = ((uae_s8)cc_offset) == 0; break;
  3117.      case sz_word: n = ((uae_s16)cc_offset) < 0; z = ((uae_s16)cc_offset) == 0; break;
  3118.      case sz_long: n = ((uae_s32)cc_offset) < 0; z = ((uae_s32)cc_offset) == 0; break;
  3119.     }
  3120. #define Bcc_TRUE 0
  3121. #define Bcc_FALSE 1
  3122.     flagsneeded = 0;
  3123.     new_cc_status = 0;
  3124.     switch (cc) {
  3125.      case 2: cc = !z ? Bcc_TRUE : Bcc_FALSE; break; /* !CFLG && !ZFLG */
  3126.      case 3: cc = z ? Bcc_TRUE : Bcc_FALSE; break; /* CFLG || ZFLG */
  3127.      case 4: cc = Bcc_TRUE; break; /* !CFLG */
  3128.      case 5: cc = Bcc_FALSE; break; /* CFLG */
  3129.      case 6: cc = !z ? Bcc_TRUE : Bcc_FALSE; break; /* !ZFLG */
  3130.      case 7: cc = z ? Bcc_TRUE : Bcc_FALSE; break; /* ZFLG */
  3131.      case 8: cc = Bcc_TRUE; break; /* !VFLG */
  3132.      case 9: cc = Bcc_FALSE; break; /* VFLG */
  3133.      case 10:cc = !n ? Bcc_TRUE : Bcc_FALSE; break; /* !NFLG */
  3134.      case 11:cc = n ? Bcc_TRUE : Bcc_FALSE; break; /* NFLG */
  3135.      case 12:cc = !n ? Bcc_TRUE : Bcc_FALSE; break; /* NFLG == VFLG */
  3136.      case 13:cc = n ? Bcc_TRUE : Bcc_FALSE; break; /* NFLG != VFLG */
  3137.      case 14:cc = !n && !z ? Bcc_TRUE : Bcc_FALSE; break; /* !ZFLG && (NFLG == VFLG) */
  3138.      case 15:cc = n || z ? Bcc_TRUE : Bcc_FALSE; break; /* ZFLG || (NFLG != VFLG) */
  3139.     }
  3140.     } else if (new_cc_status == CC_Z_FROM_86C) {
  3141.     if (cc == 6 || cc == 7) {
  3142.         cc = (cc - 2) ^ 1;
  3143.         /* Fake... */
  3144.         flagsneeded = new_cc_status = CC_C_FROM_86C;
  3145.     } else if (cc != 0 && cc != 1)
  3146.         printf("Groan!\n");
  3147.     }
  3148.     
  3149.     if (cc == 1)
  3150.     return NULL;
  3151.     
  3152.     if ((flagsneeded & new_cc_status) == flagsneeded) {
  3153.     char *result;
  3154.     /* We can generate a simple branch */
  3155.     if (cc == 0)
  3156.         assemble(0xE9);
  3157.     else
  3158.         assemble(0x0F);
  3159.     switch(cc) {
  3160.      case 2: assemble(0x87); break;          /* HI */
  3161.      case 3: assemble(0x86); break;          /* LS */
  3162.      case 4: assemble(0x83); break;          /* CC */
  3163.      case 5: assemble(0x82); break;          /* CS */
  3164.      case 6: assemble(0x85); break;          /* NE */
  3165.      case 7: assemble(0x84); break;          /* EQ */
  3166.      case 8: assemble(0x81); break;          /* VC */
  3167.      case 9: assemble(0x80); break;          /* VS */
  3168.      case 10:assemble(0x89); break;          /* PL */
  3169.      case 11:assemble(0x88); break;          /* MI */
  3170.      case 12:assemble(0x8D); break;          /* GE */
  3171.      case 13:assemble(0x8C); break;          /* LT */
  3172.      case 14:assemble(0x8F); break;          /* GT */
  3173.      case 15:assemble(0x8E); break;          /* LE */
  3174.     }
  3175.     result = compile_here();
  3176.     assemble_ulong(0);
  3177.     return result;
  3178.     }
  3179.     printf("Uhhuh.\n");
  3180.     return NULL;
  3181. }
  3182.  
  3183. static void compile_handle_bcc(struct register_mapping *map, int iip, 
  3184.                    int new_cc_status)
  3185. {
  3186.     insn_info[iip].compiled_fillin = compile_condbranch(map, iip, new_cc_status);
  3187. }
  3188.  
  3189. static void compile_handle_dbcc(struct register_mapping *map, int iip, 
  3190.                 int new_cc_status, int dreg)
  3191. {
  3192.     char *fillin1 = compile_condbranch(map, iip, new_cc_status);
  3193.     
  3194.     /* subw $1,dreg; jnc ... */
  3195.     assemble(0x66); assemble(0x83); assemble(0x05 + 5*8);
  3196.     assemble_long(regs.regs + dreg);
  3197.     assemble(1);
  3198.     assemble(0x0F); assemble(0x83);
  3199.     insn_info[iip].compiled_fillin = compile_here();
  3200.     assemble_ulong(0);
  3201.     if (fillin1 != NULL) {
  3202.     char *oldp = compile_here();
  3203.     compile_org(fillin1);
  3204.     assemble_ulong(oldp - (fillin1+4));
  3205.     compile_org(oldp);
  3206.     }
  3207. }
  3208.  
  3209. static void handle_bit_insns(struct register_mapping *map, struct ea_info *eainf,
  3210.                  int eaino_s, int eaino_d, instrmnem optype)
  3211. {
  3212.     struct ea_info *srcea = eainf + eaino_s, *dstea = eainf + eaino_d;    
  3213.     int code = (optype == i_BTST ? 0
  3214.         : optype == i_BSET ? 1
  3215.         : optype == i_BCLR ? 2
  3216.         : /* optype == i_BCHG */ 3);
  3217.  
  3218.     compile_fetchea(map, eainf, eaino_s, 5);
  3219.     compile_fetchea(map, eainf, eaino_d, 3);
  3220.  
  3221.     if (srcea->data_reg != -2) {
  3222.     compile_force_byteorder(map, srcea->data_reg, BO_NORMAL, 0);
  3223.     remove_x86r_from_cache(map, srcea->data_reg, 0);
  3224.     /* andl $something,srcreg */
  3225.     assemble(0x83); assemble(0xC0 + 4*8 + srcea->data_reg);
  3226.     if (dstea->size == sz_byte)
  3227.         assemble(7);
  3228.     else
  3229.         assemble(31);
  3230.     } else
  3231.     if (dstea->size == sz_byte)
  3232.         srcea->data_const_off &= 7;
  3233.     else
  3234.         srcea->data_const_off &= 31;
  3235.  
  3236.     /* Areg isn't possible here */
  3237.     if (dstea->mode == Dreg && dstea->data_reg == -1) {
  3238.     if (srcea->data_reg == -2) {
  3239.         assemble(0x0F); assemble(0xBA); assemble(5 + 8*(4 + code));
  3240.         assemble_long(regs.regs + dstea->reg);
  3241.         assemble(srcea->data_const_off);
  3242.     } else {
  3243.         assemble(0x0F); assemble(0xA3 + 8*code);
  3244.         assemble(5 + srcea->data_reg*8);
  3245.         assemble_long(regs.regs + dstea->reg);
  3246.     }
  3247.     } else if (dstea->data_reg >= 0) {
  3248.     compile_force_byteorder(map, dstea->data_reg, BO_NORMAL, 0);
  3249.     if (srcea->data_reg == -2) {
  3250.         assemble(0x0F); assemble(0xBA); assemble(0xC0 + dstea->data_reg + 8*(4 + code));
  3251.         assemble(srcea->data_const_off);
  3252.     } else {
  3253.         assemble(0x0F); assemble(0xA3 + 8*code);
  3254.         assemble(0xC0 + dstea->data_reg + srcea->data_reg*8);
  3255.     }
  3256.     if (optype != i_BTST)
  3257.         map->x86_dirty[dstea->data_reg] = 1;
  3258.     } else {
  3259.     int addr_code = dstea->address_reg == -2 ? 5 : dstea->address_reg + 0x80;
  3260.     compile_force_byteorder(map, dstea->address_reg, BO_NORMAL, 0);
  3261.     /* We have an address in memory */
  3262.     if (dstea->data_reg != -1)
  3263.         printf("Things don't look good in handle_bit_insns\n");
  3264.     if (srcea->data_reg == -2) {
  3265.         assemble(0x0F); assemble(0xBA); 
  3266.         assemble(addr_code + 8*(4 + code));
  3267.         assemble_long(address_space + dstea->addr_const_off);
  3268.         assemble(srcea->data_const_off);
  3269.     } else {
  3270.         assemble(0x0F); assemble(0xA3 + 8*code);
  3271.         assemble(addr_code + srcea->data_reg*8);
  3272.         assemble_long(address_space + dstea->addr_const_off);
  3273.     }
  3274.     
  3275.     }
  3276.     cc_status = CC_Z_FROM_86C;
  3277. }
  3278.  
  3279. static int do_rotshi = 1;
  3280.  
  3281. static void handle_rotshi(struct register_mapping *map, int iip, 
  3282.               uae_u8 *realpc, uaecptr current_addr, struct pid_undo *pud)
  3283. {
  3284.     struct ea_info eai;
  3285.     int amode_reg = insn_info[iip].dp->sreg;
  3286.     int amode_mode = insn_info[iip].dp->smode;
  3287.     wordsizes size = insn_info[iip].dp->size;
  3288.     int shiftcount;
  3289.     int mnemo = insn_info[iip].dp->mnemo;
  3290.     int shiftcode;
  3291.     int locked_eax_for_sahf = 0;
  3292.     
  3293.     switch(mnemo) {
  3294.      case i_ASLW: shiftcount = 1; mnemo = i_ASL; break;
  3295.      case i_ASRW: shiftcount = 1; mnemo = i_ASR; break;
  3296.      case i_LSLW: shiftcount = 1; mnemo = i_LSL; break;
  3297.      case i_LSRW: shiftcount = 1; mnemo = i_LSR; break;
  3298.      case i_ROLW: shiftcount = 1; mnemo = i_ROL; break;
  3299.      case i_RORW: shiftcount = 1; mnemo = i_ROR; break;
  3300.      case i_ROXLW:shiftcount = 1; mnemo = i_ROXL;break;
  3301.      case i_ROXRW:shiftcount = 1; mnemo = i_ROXR;break;
  3302.      default:
  3303.     amode_reg = insn_info[iip].dp->dreg;
  3304.     amode_mode = insn_info[iip].dp->dmode;
  3305.     shiftcount = insn_info[iip].dp->sreg;
  3306.     break;
  3307.     }
  3308.     if ((insn_info[iip].flags_live_at_end & CC68K_V) != 0) {
  3309.     if (mnemo == i_ASL) {
  3310.         generate_exit(map, insn_info[iip].address);
  3311.         printf("Can't handle this shift\n");
  3312.         return;
  3313.     } else if (mnemo == i_ASR || mnemo == i_LSR || mnemo == i_LSL) {
  3314.         remove_x86r_from_cache(map, r_EAX, 1);
  3315.         locked_eax_for_sahf = 1;
  3316.         lock_reg(map, r_EAX, 2);        
  3317.     }
  3318.         
  3319.     }
  3320.     if (mnemo == i_ROXR || mnemo == i_ROXL) {
  3321.     remove_x86r_from_cache(map, r_EAX, 1);
  3322.     lock_reg(map, r_EAX, 2);
  3323.     compile_move_reg_from_mem_regoffs(r_AH, -2, 4 + (uae_u32)®flags, sz_byte);
  3324.     }
  3325.     compile_prepare_undo(map, amode_mode, amode_reg, pud);
  3326.     compile_prepareea(map, amode_mode, amode_reg, size,
  3327.               &realpc, current_addr,
  3328.               &eai, 0, EA_LOAD|EA_STORE|EA_MODIFY, 1);
  3329.     
  3330.     generate_possible_exit(map, &eai, iip, pud);
  3331.     
  3332.     compile_fetchea(map, &eai, 0, 1);
  3333.     compile_force_byteorder(map, eai.data_reg, BO_NORMAL, 0);
  3334.  
  3335.     switch (mnemo) {
  3336.      case i_ASL:
  3337.     shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3338.     break;
  3339.      case i_LSL:
  3340.     shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3341.     break;    
  3342.      case i_LSR:
  3343.     shiftcode = 5; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3344.     break;
  3345.      case i_ASR:
  3346.     shiftcode = 7; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3347.     break;
  3348.      case i_ROR:
  3349.     shiftcode = 1; cc_status = CC_AFTER_RO;
  3350.     break;
  3351.      case i_ROL:
  3352.     shiftcode = 0; cc_status = CC_AFTER_RO;
  3353.     break;
  3354.      case i_ROXL:
  3355.     shiftcode = 2; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX; compile_unlock_reg(map, r_EAX);
  3356.     break;
  3357.      case i_ROXR:
  3358.     shiftcode = 3; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX; compile_unlock_reg(map, r_EAX);
  3359.     break;
  3360.     }
  3361.  
  3362.     if (size == sz_word)
  3363.     assemble(0x66);
  3364.     assemble((shiftcount == 1 ? 0xD0 : 0xC0) + (size == sz_byte ? 0 : 1));
  3365.     assemble(shiftcode*8+0xC0 + eai.data_reg);
  3366.     if (shiftcount != 1) assemble(shiftcount);
  3367.     cc_offset = 0; cc_size = size; cc_reg = eai.data_reg;
  3368.  
  3369.     if (locked_eax_for_sahf) {
  3370.     /* The trick here is that the overflow flag isn't put into AH in SAHF */
  3371.     assemble(0x9E);
  3372.     assemble(0x0B); assemble(9*1 + 0xC0);
  3373.     assemble(0x9F);
  3374.     compile_unlock_reg(map, r_EAX);
  3375.     }
  3376.     compile_note_modify(map, &eai, 0);
  3377. }
  3378.  
  3379. static void handle_rotshi_variable(struct register_mapping *map, int iip, 
  3380.                    uae_u8 *realpc, uaecptr current_addr,
  3381.                    struct pid_undo *pud)
  3382. {
  3383.     struct ea_info eais, eaid;
  3384.     int mnemo = insn_info[iip].dp->mnemo;
  3385.     int shiftcode;
  3386.     char *tmp1, *tmp2;
  3387.     int locked_eax_for_sahf = 0;
  3388.  
  3389.     remove_x86r_from_cache(map, r_ECX, 1);
  3390.     lock_reg(map, r_ECX, 2);
  3391.  
  3392.     if ((insn_info[iip].flags_live_at_end & CC68K_V) != 0) {
  3393.     if (mnemo == i_ASL) {
  3394.         generate_exit(map, insn_info[iip].address);
  3395.         printf("Can't handle this shift (var)\n");
  3396.         return;
  3397.     } else if (mnemo == i_ASR || mnemo == i_LSR || mnemo == i_LSL) {
  3398.         remove_x86r_from_cache(map, r_EAX, 1);
  3399.         locked_eax_for_sahf = 1;
  3400.         lock_reg(map, r_EAX, 2);        
  3401.     }
  3402.         
  3403.     }
  3404.     if (mnemo == i_ROXR || mnemo == i_ROXL) {
  3405.     remove_x86r_from_cache(map, r_EAX, 1);
  3406.     lock_reg(map, r_EAX, 2);
  3407.     compile_move_reg_from_mem_regoffs(r_AH, -2, 4 + (uae_u32)®flags,
  3408.                       sz_byte);
  3409.     }
  3410.     /* Both src and dest are Dreg modes */
  3411.     compile_prepareea(map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg,
  3412.               sz_long, &realpc, current_addr,
  3413.               &eais, 0, EA_LOAD, 1);
  3414.     compile_prepareea(map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg,
  3415.               insn_info[iip].dp->size, &realpc, current_addr,
  3416.               &eaid, 0, EA_LOAD|EA_STORE|EA_MODIFY, 1);
  3417.     
  3418.     compile_fetchea(map, &eais, 0, 1);
  3419.     compile_fetchea(map, &eaid, 1, 1);
  3420.     compile_force_byteorder(map, eais.data_reg, BO_NORMAL, 0);
  3421.     compile_force_byteorder(map, eaid.data_reg, BO_NORMAL, 0);
  3422.     compile_move_reg_reg(r_ECX, eais.data_reg, sz_long);
  3423.     /* Test against zero, and test bit 6. If 1 <= count <= 31, we can do the
  3424.      * operation, otherwise, we have to exit */
  3425.     assemble(0xF6); assemble(0xC0 + r_ECX); assemble(0x1F);
  3426.     assemble(0x74); assemble(9);
  3427.     assemble(0xF6); assemble(0xC0 + r_ECX); assemble(0x20);
  3428.  
  3429.     assemble(0x0F); assemble(0x85); tmp1 = compile_here(); assemble_ulong(0);
  3430.     generate_exit(map, insn_info[iip].address);
  3431.     tmp2 = compile_here(); compile_org (tmp1); assemble_ulong((tmp2-tmp1) + 4); compile_org(tmp2);
  3432.  
  3433.     switch (mnemo) {
  3434.      case i_ASL:
  3435.     shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3436.     break;
  3437.      case i_LSL:
  3438.     shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3439.     break;    
  3440.      case i_LSR:
  3441.     shiftcode = 5; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3442.     break;
  3443.      case i_ASR:
  3444.     shiftcode = 7; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3445.     break;
  3446.      case i_ROR:
  3447.     shiftcode = 1; cc_status = CC_AFTER_RO;
  3448.     break;
  3449.      case i_ROL:
  3450.     shiftcode = 0; cc_status = CC_AFTER_RO;
  3451.     break;
  3452.      case i_ROXL:
  3453.     shiftcode = 2; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX; compile_unlock_reg(map, r_EAX);
  3454.     break;
  3455.      case i_ROXR:
  3456.     shiftcode = 3; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX; compile_unlock_reg(map, r_EAX);
  3457.     break;
  3458.     }
  3459.  
  3460.     if (insn_info[iip].dp->size == sz_word)
  3461.     assemble(0x66);
  3462.     assemble(0xD2 + (insn_info[iip].dp->size == sz_byte ? 0 : 1));
  3463.     assemble(shiftcode*8+0xC0 + eaid.data_reg);
  3464.     cc_offset = 0; cc_size = insn_info[iip].dp->size; cc_reg = eaid.data_reg;
  3465.  
  3466.     if (locked_eax_for_sahf) {
  3467.     /* The trick here is that the overflow flag isn't put into AH in SAHF */
  3468.     assemble(0x9E);
  3469.     assemble(0x0B); assemble(9*1 + 0xC0);
  3470.     assemble(0x9F);
  3471.     compile_unlock_reg(map, r_EAX);
  3472.     }
  3473.     compile_note_modify(map, &eaid, 0);
  3474.     compile_unlock_reg(map, r_ECX);
  3475. }
  3476.  
  3477. static uae_u32 testmask = 0xF80000, testval = 0xF80000;
  3478.  
  3479. static int m68k_compile_block(struct hash_block *hb)
  3480. {
  3481.     int movem_extra = 0;
  3482.     int last_iip = m68k_scan_block(hb, &movem_extra);
  3483.     struct register_mapping map;
  3484.     int i, iip, szflag;
  3485.     uae_u8 *realpc_start = NULL;
  3486.     struct bb_info *current_bb;
  3487.     int cc_status_for_bcc = CC_SAHF;
  3488.     struct insn_reg_needs reg_needs_init;
  3489.     
  3490.     cesp = 0;
  3491.  
  3492.     if (n_compiled > n_max_comp)
  3493.     return 1;
  3494.     else if (n_compiled++ == n_max_comp)
  3495.     printf("X\n");
  3496.  
  3497.     cc_status = 0; compile_failure = 0;
  3498.  
  3499.     /* Kickstart ROM address? */
  3500.     if ((hb->he_first->addr & 0xF80000) != 0xF80000
  3501.     && 0 && !patched_syscalls)
  3502.     return 1;
  3503.  
  3504.     exits_necessary = ((hb->he_first->addr & 0xF80000) == 0xF80000 || !USER_PROGRAMS_BEHAVE);
  3505.     
  3506.     if (alloc_code (hb, last_iip + movem_extra) == NULL) {
  3507.     hb->allocfailed = 1;
  3508.     return 0;
  3509.     }
  3510.     compile_org(hb->compile_start);
  3511.     compile_last_addr = (char *)hb->compile_start + hb->alloclen;
  3512.     
  3513.     /* m68k_scan_block() will leave this all set up */
  3514.     current_bb = bb_stack;
  3515.     
  3516.     for (i = 0; i < 8; i++) {
  3517.     map.dreg_map[i] = map.areg_map[i] = -1;
  3518.     map.x86_dirty[i] = 0;
  3519.     map.x86_cache_reg[i] = -1;
  3520.     map.x86_cr_type[i] = 0;
  3521.     map.x86_const_offset[i] = 0;
  3522.     map.x86_verified[i] = 0;
  3523.     map.x86_byteorder[i] = BO_NORMAL;
  3524.     }
  3525.     
  3526.     reg_needs_init.checkpoint_no = 0;
  3527.     for (i = 0; i < 8; i++) {
  3528.     reg_needs_init.dreg_needed[i] = reg_needs_init.areg_needed[i] = -1;
  3529.     reg_needs_init.dreg_mask[i] = reg_needs_init.areg_mask[i] = ALL_X86_REGS;
  3530.     }
  3531.     
  3532.     for (iip = 0; iip < last_iip && !compile_failure; iip++) {
  3533.     uae_u8 *realpc;
  3534.     struct ea_info eainfo[8];
  3535.     uaecptr current_addr;
  3536.     struct pid_undo pub;
  3537.     struct insn_reg_needs this_reg_needs = reg_needs_init;
  3538.  
  3539.     /* Set up locks for a new insn. We don't bother to clear this
  3540.      * properly after compiling one insn. */
  3541.     for (i = 0; i < 8; i++) {
  3542.         map.x86_users[i] = i == r_ESP ? 1 : 0;
  3543.         map.x86_locked[i] = i == r_ESP ? 2 : 0;
  3544.     }
  3545.  
  3546.     pub.used = 0;
  3547.     current_addr = insn_info[iip].address + 2;
  3548.  
  3549.     if (iip == current_bb->first_iip) {
  3550.         sync_reg_cache(&map, 1);
  3551.         if (!quiet_compile)
  3552.         printf("Compiling %08lx\n", current_bb->h->addr);
  3553.  
  3554.         realpc_start = get_real_address(current_bb->h->addr);
  3555.         current_bb->h->execute = (code_execfunc)compile_here();
  3556.         current_bb->h->matchword = *(uae_u32 *)realpc_start;
  3557.         cc_status_for_bcc = CC_SAHF;
  3558.     }
  3559.  
  3560.     realpc = realpc_start + (current_addr - current_bb->h->addr);    
  3561.  
  3562.     insn_info[iip].compiled_jumpaddr = compile_here();        
  3563.     insn_info[iip].compiled_fillin = NULL;
  3564.     
  3565.     if (insn_info[iip].jump_target) {
  3566.         if (cesp == CE_STACK_SIZE) {
  3567.         generate_exit(NULL, insn_info[iip].address);
  3568.         compile_failure = 1;
  3569.         } else {
  3570.         assemble(0xFE); assemble(0x05 + 8*1); assemble_long(&nr_bbs_to_run);
  3571.         assemble(0x0F); assemble(0x84); /* JE finish */
  3572.         compile_exit_stack[cesp].noflush = 1;
  3573.         compile_exit_stack[cesp].address = current_bb->h;
  3574.         compile_exit_stack[cesp].jmpoffs = compile_here();
  3575.         assemble_ulong(0);
  3576.         cesp++;
  3577.         }
  3578.     }
  3579.     /*
  3580.      * This will sort out all insns we can't compile, including
  3581.      * jumps out of this block */
  3582.     if (insn_info[iip].stop_translation == 1) {
  3583.         generate_exit(&map, insn_info[iip].address);
  3584.         cc_status = 0;
  3585.     } else switch (insn_info[iip].dp->mnemo) {
  3586.      case i_NOP:
  3587.         cc_status = 0;
  3588.         if (!quiet_compile)
  3589.         printf("Compiling a NOP\n");
  3590.         break;
  3591.  
  3592.      case i_RTS:
  3593.         sync_reg_cache(&map, 1);
  3594.         lock_reg(&map, r_ECX, 2);
  3595.         lock_reg(&map, r_EBX, 2);
  3596.         {
  3597.         char *tmp1, *tmp2, *tmp3;
  3598.  
  3599.         /* fetch (A7) */
  3600.         assemble(0x8B); assemble(0x5 + r_EBX*8); assemble_long(regs.regs + 15);
  3601.         assemble(0x8B); assemble(0x80 + 9*r_EBX); assemble_long(address_space);
  3602.         assemble(0x0F); /* bswapl x86r */
  3603.         assemble(0xC8 + r_EBX);
  3604.         /* fetch jsr_num */
  3605.         assemble(0x8B); assemble(0x5 + r_ECX*8); assemble_long(&jsr_num);
  3606.         assemble(0x09); assemble(0xC0 + 9*r_ECX);
  3607.         assemble(0x0F); assemble(0x84); tmp1 = compile_here(); assemble_ulong(0);
  3608.         assemble(0xFF); assemble(1*8 + 0xC0 + r_ECX);
  3609.         /* cmpl %ebx,disp32(,%ecx,4) */
  3610.         assemble(0x39); assemble(0x04 + 8*r_EBX); assemble(0x8d);
  3611.         assemble_long(jsr_rets);
  3612.         assemble(0x0F); assemble(0x85); tmp2 = compile_here(); assemble_ulong(0);
  3613.         /* movl disp32(,%ecx,4),%ebx */
  3614.         assemble(0x8B); assemble(0x04 + 8*r_EBX); assemble(0x8d);
  3615.         assemble_long(jsr_hash);
  3616.         /* movl execute(%ebx), %ebx */
  3617.         assemble(0x8B); assemble(0x040 + 9*r_EBX); assemble((int)&((struct hash_entry *)0)->execute);
  3618.         assemble(0x09); assemble(0xC0 + 9*r_EBX);
  3619.         assemble(0x0F); assemble(0x85); tmp3 = compile_here(); assemble_ulong(0);
  3620.         compile_org(tmp1); assemble_ulong(tmp3 - tmp1);
  3621.         compile_org(tmp2); assemble_ulong(tmp3 - tmp2);
  3622.         compile_org(tmp3 + 4);
  3623.         generate_exit(&map, insn_info[iip].address);
  3624.         tmp1 = compile_here();
  3625.         compile_org(tmp3); assemble_ulong((tmp1-tmp3)-4);
  3626.         compile_org(tmp1);
  3627.         assemble(0x89); assemble(0x5 + r_ECX*8); assemble_long(&jsr_num);
  3628.         assemble(0x83); assemble(0x05 + 5*8); assemble_long(regs.regs + 15); assemble(-4);
  3629.         /* Off we go */
  3630.         assemble(0xFF); assemble(4*8 + 0xC0 + r_EBX);        
  3631.         }
  3632.         break;
  3633.         
  3634.      case i_JMP:
  3635.         sync_reg_cache(&map, 1);
  3636.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3637.                   insn_info[iip].dp->sreg, 
  3638.                   insn_info[iip].dp->size, &realpc, current_addr,
  3639.                   eainfo, 0, EA_LOAD, 1);
  3640.         {
  3641.         char *tmp1, *tmp2, *tmp3;
  3642.  
  3643.         struct hash_entry *tmph;
  3644.         if (eainfo[0].address_reg != -2 || (tmph = get_hash_for_func(eainfo[0].addr_const_off, 1)) == 0) {
  3645.             if (eainfo[0].address_reg != -2 && !quiet_compile)
  3646.             printf("Can't compile indirect JMP\n");
  3647.             generate_exit(&map, insn_info[iip].address);
  3648.             break;
  3649.         }
  3650.         /* check whether the destination has compiled code */
  3651.         assemble(0x8B); assemble(r_EBX*8 + 0x05); assemble_long(&(tmph->execute));
  3652.         assemble(0x09); assemble(0xC0 + 9*r_EBX);
  3653.         assemble(0x0F); assemble(0x85); tmp1 = compile_here(); assemble_ulong(0);
  3654.         generate_exit(&map, insn_info[iip].address);
  3655.         tmp2 = compile_here(); compile_org(tmp1); 
  3656.         assemble_ulong((tmp2 - tmp1) - 4);
  3657.         compile_org(tmp2);
  3658.         /* Off we go */
  3659.         assemble(0xFF); assemble(4*8 + 0xC0 + r_EBX);
  3660.         }
  3661.         cc_status = 0;
  3662.         break;
  3663.  
  3664.      case i_JSR:
  3665.         sync_reg_cache(&map, 1);
  3666.         lock_reg(&map, r_ECX, 2);
  3667.         lock_reg(&map, r_EBX, 2);
  3668.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3669.                   insn_info[iip].dp->sreg, 
  3670.                   insn_info[iip].dp->size, &realpc, current_addr,
  3671.                   eainfo, 0, EA_LOAD, 1);
  3672.         {
  3673.         char *tmp1, *tmp2, *tmp3;
  3674.  
  3675.         struct hash_entry *tmph;
  3676.         if (eainfo[0].address_reg != -2 || (tmph = get_hash_for_func(eainfo[0].addr_const_off, 1)) == 0) {
  3677.             if (eainfo[0].address_reg != -2 && !quiet_compile)
  3678.             printf("Can't compile indirect JSR\n");
  3679.             generate_exit(&map, insn_info[iip].address);
  3680.             break;
  3681.         }
  3682.         assert(iip + 1 < last_iip);
  3683.         assert(iip == current_bb->last_iip);
  3684.         /* check whether the destination has compiled code */
  3685.         assemble(0x8B); assemble(r_EBX*8 + 0x05); assemble_long(&(tmph->execute));
  3686.         assemble(0x09); assemble(0xC0 + 9*r_EBX);
  3687.         assemble(0x0F); assemble(0x84); tmp3 = compile_here(); assemble_ulong(0);
  3688.         /* check for stack overflow */
  3689.         assemble(0x8B); assemble(r_ECX*8 + 0x05); assemble_long(&jsr_num);
  3690.         assemble(0xF7); assemble(0xC0+r_ECX); assemble_ulong(MAX_JSRS);
  3691.         assemble(0x0F); assemble(0x84); tmp1 = compile_here(); assemble_ulong(0);
  3692.         generate_exit(&map, insn_info[iip].address);
  3693.         tmp2 = compile_here(); compile_org(tmp1); assemble_ulong((tmp2 - tmp1) - 4);
  3694.         compile_org(tmp3); assemble_ulong(tmp1-tmp3);
  3695.         compile_org(tmp2);
  3696.         /* movl $something,disp32(,%ecx,4) */
  3697.         assemble(0xC7); assemble(0x04); assemble(0x8d); 
  3698.         assemble_long(jsr_rets); assemble_ulong(insn_info[iip+1].address);
  3699.         assemble(0xC7); assemble(0x04); assemble(0x8d); 
  3700.         assemble_long(jsr_hash); assemble_long((current_bb + 1)->h);
  3701.         /* incl jsr_num */
  3702.         assemble(0xFF); assemble(0x05); assemble_long(&jsr_num);
  3703.         /* Put things on the 68k stack */
  3704.         assemble(0x83); assemble(0x05 + 5*8); assemble_long(regs.regs + 15); assemble(4);
  3705.         assemble(0x8B); assemble(r_ECX*8+ 0x05); assemble_long(regs.regs + 15);
  3706.         assemble(0xC7); assemble(0x80 + r_ECX); assemble_long(address_space); 
  3707.         assemble_ulong_68k(insn_info[iip+1].address);
  3708.         /* Off we go */
  3709.         assemble(0xFF); assemble(4*8 + 0xC0 + r_EBX);
  3710.         }
  3711.         break;
  3712.  
  3713.      case i_BSR:
  3714.         sync_reg_cache(&map, 1);
  3715.         lock_reg(&map, r_ECX, 2);
  3716.         lock_reg(&map, r_EBX, 2);
  3717.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3718.                   insn_info[iip].dp->sreg, 
  3719.                   insn_info[iip].dp->size, &realpc, current_addr,
  3720.                   eainfo, 0, EA_LOAD, 1);
  3721.         {
  3722.         char *tmp1, *tmp2, *tmp3;
  3723.         uaecptr dest = insn_info[iip].address + 2 + (uae_s32)eainfo[0].data_const_off;
  3724.         struct hash_entry *tmph;
  3725.         if ((tmph = get_hash_for_func(dest, 1)) == 0) {
  3726.             generate_exit(&map, insn_info[iip].address);
  3727.             break;
  3728.         }
  3729.         assert(iip + 1 < last_iip);
  3730.         assert(iip == current_bb->last_iip);
  3731.  
  3732.         /* check whether the destination has compiled code */
  3733.         assemble(0x8B); assemble(r_EBX*8 + 0x05); assemble_long(&(tmph->execute));
  3734.         assemble(0x09); assemble(0xC0 + 9*r_EBX);
  3735.         assemble(0x0F); assemble(0x84); tmp3 = compile_here(); assemble_ulong(0);
  3736.         /* check for stack overflow */
  3737.         assemble(0x8B); assemble(r_ECX*8 + 0x05); assemble_long(&jsr_num);
  3738.         assemble(0xF7); assemble(0xC0+r_ECX); assemble_ulong(MAX_JSRS);
  3739.         assemble(0x0F); assemble(0x84); tmp1 = compile_here(); assemble_ulong(0);
  3740.         generate_exit(&map, insn_info[iip].address);
  3741.         tmp2 = compile_here(); compile_org(tmp1); assemble_ulong((tmp2 - tmp1) - 4);
  3742.         compile_org(tmp3); assemble_ulong(tmp1-tmp3);
  3743.         compile_org(tmp2);
  3744.         /* movl $something,disp32(,%ecx,4) */
  3745.         assemble(0xC7); assemble(0x04); assemble(0x8d); 
  3746.         assemble_long(jsr_rets); assemble_ulong(insn_info[iip+1].address);
  3747.         assemble(0xC7); assemble(0x04); assemble(0x8d); 
  3748.         assemble_long(jsr_hash); assemble_long((current_bb + 1)->h);
  3749.         /* incl jsr_num */
  3750.         assemble(0xFF); assemble(0x05); assemble_long(&jsr_num);
  3751.         /* Put things on the 68k stack */
  3752.         assemble(0x83); assemble(0x05 + 5*8); assemble_long(regs.regs + 15); assemble(4);
  3753.         assemble(0x8B); assemble(r_ECX*8+ 0x05); assemble_long(regs.regs + 15);
  3754.         assemble(0xC7); assemble(0x80 + r_ECX); assemble_long(address_space); 
  3755.         assemble_ulong_68k(insn_info[iip+1].address);
  3756.         /* Off we go */
  3757.         assemble(0xFF); assemble(4*8 + 0xC0 + r_EBX);
  3758.         }
  3759.         break;
  3760.         
  3761.      case i_Bcc:
  3762.         sync_reg_cache(&map, 0);
  3763.         compile_handle_bcc(&map, iip, cc_status_for_bcc);
  3764.         cc_status = 0;
  3765.         break;
  3766.  
  3767.      case i_DBcc:
  3768.         sync_reg_cache(&map, 0);
  3769.         remove_x86r_from_cache(&map, map.dreg_map[insn_info[iip].dp->sreg], 1);
  3770.         compile_handle_dbcc(&map, iip, cc_status_for_bcc,
  3771.                 insn_info[iip].dp->sreg);
  3772.         cc_status = 0;
  3773.         break;
  3774. #if 0
  3775.      case i_Scc:
  3776.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  3777.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3778.                   insn_info[iip].dp->sreg, 
  3779.                   insn_info[iip].dp->size, &realpc, current_addr,
  3780.                   eainfo, 0, EA_STORE, 1);
  3781.  
  3782.         generate_possible_exit(&map, eainfo, iip, &pub);
  3783.         srcreg2 = get_;
  3784.         compile_note_modify(&map, eainfo, 0);
  3785.  
  3786.         cc_status = 0;
  3787.         break;
  3788. #endif
  3789.      case i_ADD:
  3790.      case i_SUB:
  3791.      case i_CMP:
  3792.      case i_CMPM:
  3793.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  3794.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  3795.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3796.                   insn_info[iip].dp->sreg, 
  3797.                   insn_info[iip].dp->size, &realpc, current_addr,
  3798.                   eainfo, 0, EA_LOAD, 1);
  3799.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3800.                   insn_info[iip].dp->dreg, 
  3801.                   insn_info[iip].dp->size, &realpc, current_addr,
  3802.                   eainfo, 1, 
  3803.                   (insn_info[iip].dp->mnemo == i_ADD || insn_info[iip].dp->mnemo == i_SUB 
  3804.                    ? EA_MODIFY | EA_LOAD | EA_STORE
  3805.                    : EA_LOAD | EA_STORE), 1);
  3806.  
  3807.         generate_possible_exit(&map, eainfo, iip, &pub);
  3808.         generate_possible_exit(&map, eainfo+1, iip, &pub);
  3809.         
  3810.         compile_loadeas(&map, eainfo, 0, 1, binop_alternatives, 0, 1);
  3811.  
  3812.         switch (insn_info[iip].dp->mnemo) {
  3813.          case i_ADD: compile_eas(&map, eainfo, 0, 1, 0); break;
  3814.          case i_SUB: compile_eas(&map, eainfo, 0, 1, 5); break;
  3815.          case i_CMP: case i_CMPM: compile_eas(&map, eainfo, 0, 1, 7); break;
  3816.         }
  3817.         
  3818.         if (insn_info[iip].dp->mnemo != i_CMP && insn_info[iip].dp->mnemo != i_CMPM)
  3819.         compile_note_modify(&map, eainfo, 1);
  3820.         switch (insn_info[iip].dp->mnemo) {
  3821.          case i_ADD:
  3822.          case i_SUB:
  3823.         cc_status = CC_X_FROM_86C | CC_Z_FROM_86Z | CC_C_FROM_86C | CC_V_FROM_86V | CC_N_FROM_86N;
  3824.         break;
  3825.          case i_CMP:
  3826.          case i_CMPM:
  3827.         cc_status = CC_Z_FROM_86Z | CC_C_FROM_86C | CC_V_FROM_86V | CC_N_FROM_86N;
  3828.         break;
  3829.         }
  3830.         break;
  3831.  
  3832.      case i_ADDX:
  3833.      case i_SUBX:
  3834.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  3835.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  3836.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3837.                   insn_info[iip].dp->sreg, 
  3838.                   insn_info[iip].dp->size, &realpc, current_addr,
  3839.                   eainfo, 0, EA_LOAD, 1);
  3840.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3841.                   insn_info[iip].dp->dreg, 
  3842.                   insn_info[iip].dp->size, &realpc, current_addr,
  3843.                   eainfo, 1, EA_MODIFY | EA_LOAD | EA_STORE, 1);
  3844.  
  3845.         generate_possible_exit(&map, eainfo, iip, &pub);
  3846.         generate_possible_exit(&map, eainfo+1, iip, &pub);
  3847.  
  3848.         compile_loadeas(&map, eainfo, 0, 1, binop_alternatives, 0, 1);
  3849.  
  3850.         /* bt $0, regflags+4 ; get carry */
  3851.         assemble(0x0F); assemble(0xBA); assemble(0x5+4*8); 
  3852.         assemble_ulong(4 + (uae_u32)®flags); assemble(0);
  3853.  
  3854.         switch (insn_info[iip].dp->mnemo) {
  3855.          case i_ADDX: compile_eas(&map, eainfo, 0, 1, 2); break;
  3856.          case i_SUBX: compile_eas(&map, eainfo, 0, 1, 3); break;
  3857.         }        
  3858.         compile_note_modify(&map, eainfo, 1);
  3859.  
  3860.         if (insn_info[iip].flags_live_at_end & CC68K_Z) {
  3861.         /* Darn. */
  3862.         int tmpr = get_free_x86_register(&map, ALL_X86_REGS);
  3863.         /* pushfl; popl tmpr */
  3864.         assemble(0x9C); assemble(0x58+tmpr);
  3865.         /* Magic! */
  3866.         /* andl tmpr, regflags; andl $~0x40,tmpr; orl tmpr, regflags */
  3867.         assemble(0x21); assemble(0x05 + 8*tmpr); assemble_long(®flags);
  3868.         assemble(0x81); assemble(0xC0 + 8*4 + tmpr); assemble_ulong(~0x40);
  3869.         assemble(0x09); assemble(0x05 + 8*tmpr); assemble_long(®flags);
  3870.         compile_move_reg_to_mem_regoffs(-2, 4 + (uae_u32)®flags, tmpr, sz_long);
  3871.         cc_status = 0;
  3872.         } else {
  3873.         /* Lies! */
  3874.         cc_status = CC_X_FROM_86C | CC_Z_FROM_86Z |CC_C_FROM_86C |CC_V_FROM_86V |CC_N_FROM_86N;
  3875.         }
  3876.         break;
  3877.  
  3878.      case i_MULU:
  3879.      case i_MULS:
  3880.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  3881.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  3882.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3883.                   insn_info[iip].dp->sreg, 
  3884.                   insn_info[iip].dp->size, &realpc, current_addr,
  3885.                   eainfo, 0, EA_LOAD, 1);
  3886.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3887.                   insn_info[iip].dp->dreg, 
  3888.                   insn_info[iip].dp->size, &realpc, current_addr,
  3889.                   eainfo, 1, EA_MODIFY | EA_LOAD | EA_STORE, 1);
  3890.  
  3891.         generate_possible_exit(&map, eainfo, iip, &pub);
  3892.         generate_possible_exit(&map, eainfo+1, iip, &pub);
  3893.         
  3894.         compile_loadeas(&map, eainfo, 0, 1, regonly_alternatives, 0, 1);
  3895.  
  3896.         /* Extend the regs properly */
  3897.         remove_x86r_from_cache(&map, eainfo[0].data_reg, 0);
  3898.         switch (insn_info[iip].dp->mnemo) {
  3899.          case i_MULU:
  3900.         assemble(0x81); assemble(0xC0+4*8 + eainfo[0].data_reg); assemble_ulong(0xFFFF);
  3901.         assemble(0x81); assemble(0xC0+4*8 + eainfo[1].data_reg); assemble_ulong(0xFFFF);
  3902.         break;
  3903.          case i_MULS:
  3904.         assemble(0x0F); assemble(0xBF); assemble(0xC0 + 9*eainfo[0].data_reg);
  3905.         assemble(0x0F); assemble(0xBF); assemble(0xC0 + 9*eainfo[1].data_reg);
  3906.         break;
  3907.         }
  3908.         /* and multiply */
  3909.         assemble(0x0F); assemble(0xAF); assemble(0xC0 + 8*eainfo[1].data_reg + eainfo[0].data_reg);
  3910.         compile_note_modify(&map, eainfo, 1);
  3911.         cc_status = CC_TEST_REG;
  3912.         cc_reg = eainfo[1].data_reg;
  3913.         cc_offset = 0;
  3914.         cc_size = sz_long;
  3915.         break;
  3916.  
  3917.      case i_ADDA:
  3918.      case i_SUBA:
  3919.      case i_CMPA:
  3920.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  3921.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  3922.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3923.                   insn_info[iip].dp->sreg, 
  3924.                   insn_info[iip].dp->size, &realpc, current_addr,
  3925.                   eainfo, 0, EA_LOAD, 1);
  3926.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3927.                   insn_info[iip].dp->dreg, 
  3928.                   sz_long, &realpc, current_addr,
  3929.                   eainfo, 1, 
  3930.                   (insn_info[iip].dp->mnemo == i_ADDA || insn_info[iip].dp->mnemo == i_SUBA
  3931.                    ? EA_MODIFY | EA_LOAD | EA_STORE
  3932.                    : EA_LOAD | EA_STORE), 
  3933.                   1);
  3934.  
  3935.         generate_possible_exit(&map, eainfo, iip, &pub);
  3936.  
  3937.         compile_loadeas(&map, eainfo, 0, 1,
  3938.                 insn_info[iip].dp->size == sz_word ? binop_worda_alternatives : binop_alternatives,
  3939.                 0, 1);
  3940.  
  3941.         if (insn_info[iip].dp->size == sz_word) {
  3942.         remove_x86r_from_cache(&map, eainfo[0].data_reg, 0);
  3943.         compile_extend_long(&map, eainfo[0].data_reg, sz_word);
  3944.         }
  3945.         eainfo[0].size = sz_long;
  3946.  
  3947.         switch (insn_info[iip].dp->mnemo) {
  3948.          case i_ADDA: compile_eas(&map, eainfo, 0, 1, 0); break;
  3949.          case i_SUBA: compile_eas(&map, eainfo, 0, 1, 5); break;
  3950.          case i_CMPA: compile_eas(&map, eainfo, 0, 1, 7); break;
  3951.         }
  3952.  
  3953.         if (insn_info[iip].dp->mnemo == i_CMPA) {
  3954.         cc_status = CC_Z_FROM_86Z |CC_C_FROM_86C |CC_V_FROM_86V |CC_N_FROM_86N;
  3955.         } else {
  3956.         compile_note_modify(&map, eainfo, 1);
  3957.         cc_status = 0;
  3958.         }
  3959.         break;
  3960.  
  3961.      case i_MOVE:
  3962.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  3963.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  3964.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3965.                   insn_info[iip].dp->sreg, 
  3966.                   insn_info[iip].dp->size, &realpc, current_addr,
  3967.                   eainfo, 0, EA_LOAD, 1);
  3968.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3969.                   insn_info[iip].dp->dreg, 
  3970.                   insn_info[iip].dp->size, &realpc, current_addr,
  3971.                   eainfo, 1, EA_STORE, 1);
  3972.  
  3973.         generate_possible_exit(&map, eainfo, iip, &pub);
  3974.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  3975.         
  3976.         compile_loadeas(&map, eainfo, 0, 1, binop_alternatives, 1, 0);
  3977.         compile_storeea(&map, eainfo, 0, 1);
  3978.         
  3979.         if (eainfo[0].data_reg == -2) {
  3980.         cc_status = CC_TEST_REG;
  3981.         cc_reg = -2;
  3982.         cc_offset = eainfo[0].data_const_off;
  3983.         } else if (eainfo[0].data_reg == -1) {
  3984.         if (eainfo[1].data_reg == -1)
  3985.             printf("Don't know where to get flags from\n");
  3986.         cc_status = CC_TEST_REG;
  3987.         cc_offset = 0;
  3988.         cc_reg = eainfo[1].data_reg;
  3989.         } else {
  3990.         cc_status = CC_TEST_REG;
  3991.         cc_reg = eainfo[0].data_reg;
  3992.         cc_offset = 0;
  3993.         }
  3994.         cc_size = eainfo[0].size;
  3995.         
  3996.         break;
  3997.  
  3998.      case i_MOVEA:
  3999.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  4000.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  4001.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4002.                   insn_info[iip].dp->sreg, 
  4003.                   insn_info[iip].dp->size, &realpc, current_addr,
  4004.                   eainfo, 0, EA_LOAD, 1);
  4005.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4006.                   insn_info[iip].dp->dreg,
  4007.                   sz_long, &realpc, current_addr,
  4008.                   eainfo, 1, EA_STORE, 1);
  4009.  
  4010.         generate_possible_exit(&map, eainfo, iip, &pub);
  4011.         
  4012.         compile_loadeas(&map, eainfo, 0, 1,
  4013.                 insn_info[iip].dp->size == sz_word ? binop_worda_alternatives : binop_alternatives,
  4014.                 0, 0);
  4015.  
  4016.         if (insn_info[iip].dp->size == sz_word) {
  4017.         remove_x86r_from_cache(&map, eainfo[0].data_reg, 0);
  4018.         compile_extend_long(&map, eainfo[0].data_reg, sz_word);
  4019.         }
  4020.         eainfo[0].size = sz_long;
  4021.  
  4022.         compile_storeea(&map, eainfo, 0, 1);
  4023.  
  4024.         cc_status = 0;
  4025.         break;
  4026.  
  4027.      case i_EXG:
  4028.         if (insn_info[iip].dp->smode != insn_info[iip].dp->dmode
  4029.         || insn_info[iip].dp->sreg != insn_info[iip].dp->dreg) 
  4030.         {
  4031.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4032.                   insn_info[iip].dp->sreg,
  4033.                   sz_long, &realpc, current_addr,
  4034.                   eainfo, 0, EA_LOAD|EA_STORE, 1);
  4035.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4036.                   insn_info[iip].dp->dreg,
  4037.                   sz_long, &realpc, current_addr,
  4038.                   eainfo, 1, EA_LOAD|EA_STORE, 1);
  4039.  
  4040.         compile_loadeas(&map, eainfo, 0, 1, regonly_alternatives, 0, 1);
  4041.         compile_storeea(&map, eainfo, 1, 0);
  4042.         compile_storeea(&map, eainfo, 0, 1);
  4043.         }
  4044.  
  4045.         cc_status = 0;
  4046.         break;
  4047.         
  4048.      case i_LINK:
  4049.         compile_prepare_undo(&map, Apdi, 7, &pub);
  4050.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4051.                   insn_info[iip].dp->sreg, 
  4052.                   sz_long, &realpc, current_addr,
  4053.                   eainfo, 0, EA_LOAD|EA_STORE, 1);
  4054.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4055.                   insn_info[iip].dp->dreg,
  4056.                   sz_long, &realpc, current_addr,
  4057.                   eainfo, 1, EA_LOAD, 1);
  4058.         compile_prepareea(&map, Apdi, 7, sz_long, &realpc, current_addr,
  4059.                   eainfo, 2, EA_STORE, 1);
  4060.  
  4061.         generate_possible_exit(&map, eainfo+2, iip, &pub);
  4062.  
  4063.         compile_fetchea(&map, eainfo, 0, 1);
  4064.         /* we know this is a constant - no need to fetch it*/
  4065.         /* compile_fetchea(&map, eainfo, 1); */
  4066.         compile_storeea(&map, eainfo, 0, 2); /* An -> -(A7) */
  4067.  
  4068.         compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
  4069.                   eainfo, 3, EA_STORE, 1);
  4070.         compile_fetchea(&map, eainfo, 3, 1);
  4071.         compile_storeea(&map, eainfo, 3, 0); /* A7 -> An */
  4072.  
  4073.         /* @@@ 020 */
  4074.         compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
  4075.                   eainfo, 4, EA_LOAD, 1);
  4076.         compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
  4077.                   eainfo, 5, EA_STORE, 1);
  4078.         compile_fetchea(&map, eainfo, 4, 1);
  4079.         eainfo[4].data_const_off += (uae_s16)eainfo[1].data_const_off;
  4080.         compile_storeea(&map, eainfo, 4, 5); /* A7+off -> A7 */
  4081.         cc_status = 0;
  4082.         break;
  4083.                 
  4084.      case i_UNLK:
  4085.         compile_prepareea(&map, Areg,
  4086.                   insn_info[iip].dp->sreg, 
  4087.                   sz_long, &realpc, current_addr,
  4088.                   eainfo, 0, EA_LOAD, 1);
  4089.         compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
  4090.                   eainfo, 1, EA_STORE, 1);
  4091.         
  4092.         generate_possible_exit(&map, eainfo + 0, iip, &pub);
  4093.  
  4094.         compile_fetchea(&map, eainfo, 0, 1);
  4095.         compile_storeea(&map, eainfo, 0, 1);
  4096.  
  4097.         /* The Apdi could of course point to a non-memory area, but undos
  4098.          * are difficult here, and anyway: which program does evil hacks
  4099.          * with UNLK? */
  4100.         compile_prepareea(&map, Aipi, 7, sz_long, &realpc, current_addr,
  4101.                   eainfo, 2, EA_LOAD, 1);
  4102.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4103.                   insn_info[iip].dp->sreg, 
  4104.                   sz_long, &realpc, current_addr,
  4105.                   eainfo, 3, EA_STORE, 1);
  4106.         compile_fetchea(&map, eainfo, 2, 1);
  4107.         compile_storeea(&map, eainfo, 2, 3);
  4108.  
  4109.         cc_status = 0;        
  4110.         break;
  4111.  
  4112.      case i_OR:
  4113.      case i_AND:
  4114.      case i_EOR:
  4115.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  4116.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  4117.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4118.                   insn_info[iip].dp->sreg, 
  4119.                   insn_info[iip].dp->size, &realpc, current_addr,
  4120.                   eainfo, 0, EA_LOAD, 1);
  4121.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4122.                   insn_info[iip].dp->dreg, 
  4123.                   insn_info[iip].dp->size, &realpc, current_addr,
  4124.                   eainfo, 1, EA_MODIFY | EA_LOAD | EA_STORE, 1);
  4125.  
  4126.         generate_possible_exit(&map, eainfo, iip, &pub);
  4127.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  4128.         
  4129.         compile_loadeas(&map, eainfo, 0, 1, binop_alternatives, 0, 1);
  4130.  
  4131.         switch (insn_info[iip].dp->mnemo) {
  4132.          case i_AND: compile_eas(&map, eainfo, 0, 1, 4); break;
  4133.          case i_EOR: compile_eas(&map, eainfo, 0, 1, 6); break;
  4134.          case i_OR:  compile_eas(&map, eainfo, 0, 1, 1); break;
  4135.         }
  4136.         
  4137.         compile_note_modify(&map, eainfo, 1);
  4138.         cc_status = CC_Z_FROM_86Z | CC_C_FROM_86C | CC_V_FROM_86V | CC_N_FROM_86N;
  4139.         break;
  4140.  
  4141.      case i_TST:
  4142.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  4143.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4144.                   insn_info[iip].dp->sreg, 
  4145.                   insn_info[iip].dp->size, &realpc, current_addr,
  4146.                   eainfo, 0, EA_LOAD, 1);
  4147.  
  4148.         generate_possible_exit(&map, eainfo, iip, &pub);
  4149.         
  4150.         compile_fetchea(&map, eainfo, 0, 1);
  4151.         cc_status = CC_TEST_REG;
  4152.         cc_reg = eainfo[0].data_reg;
  4153.         cc_offset = 0;
  4154.         cc_size = eainfo[0].size;
  4155.         break;
  4156.         
  4157.      case i_CLR:
  4158.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  4159.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4160.                   insn_info[iip].dp->sreg, 
  4161.                   insn_info[iip].dp->size, &realpc, current_addr,
  4162.                   eainfo, 0, EA_STORE, 1);
  4163.         compile_prepareea(&map, immi, 0, sz_long, &realpc, current_addr,
  4164.                   eainfo, 1, EA_LOAD, 1);
  4165.         generate_possible_exit(&map, eainfo + 0, iip, &pub);
  4166.         compile_loadeas(&map, eainfo, 1, 0, binop_alternatives, 1, 0);
  4167.         compile_storeea(&map, eainfo, 1, 0);
  4168.  
  4169.         cc_status = CC_TEST_REG;
  4170.         cc_reg = -2;
  4171.         cc_offset = 0;
  4172.         cc_size = eainfo[0].size;
  4173.         break;
  4174.  
  4175.      case i_EXT:
  4176.         /* No exits, no undo - this is always a Dreg; fetchea will get it in a reg
  4177.          * without offset */
  4178.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4179.                   insn_info[iip].dp->sreg, 
  4180.                   insn_info[iip].dp->size == sz_long ? sz_word : sz_byte,
  4181.                   &realpc, current_addr,
  4182.                   eainfo, 0, EA_LOAD|EA_STORE, 1);
  4183.         compile_fetchea(&map, eainfo, 0, 1);
  4184.         compile_force_byteorder(&map, eainfo[0].data_reg, BO_NORMAL, 0);
  4185.  
  4186.         if (insn_info[iip].dp->size == sz_word)
  4187.         assemble(0x66);
  4188.         assemble(0x0F);
  4189.         if (insn_info[iip].dp->size == sz_long)
  4190.         assemble(0xBF);
  4191.         else
  4192.         assemble(0xBE);
  4193.         
  4194.         assemble(0xC0 + 9*eainfo[0].data_reg);
  4195.         map.x86_dirty[eainfo[0].data_reg] = 1;
  4196.  
  4197.         cc_status = CC_TEST_REG;
  4198.         cc_reg = eainfo[0].data_reg;
  4199.         cc_offset = 0;
  4200.         cc_size = eainfo[0].size;        
  4201.         break;
  4202.  
  4203.      case i_NOT:
  4204.      case i_NEG:
  4205.         szflag = insn_info[iip].dp->size == sz_byte ? 0 : 1;
  4206.  
  4207.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  4208.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4209.                   insn_info[iip].dp->sreg, 
  4210.                   insn_info[iip].dp->size,
  4211.                   &realpc, current_addr,
  4212.                   eainfo, 0, EA_LOAD|EA_STORE, 1);
  4213.  
  4214.         generate_possible_exit(&map, eainfo, iip, &pub);
  4215.         
  4216.         compile_fetchea(&map, eainfo, 0, 1);
  4217.         compile_force_byteorder(&map, eainfo[0].data_reg, BO_NORMAL, 0);
  4218.  
  4219.         if (insn_info[iip].dp->size == sz_word)
  4220.         assemble(0x66);
  4221.         assemble(0xF6 + szflag);
  4222.         
  4223.         assemble(0xC0 + eainfo[0].data_reg + 8*(insn_info[iip].dp->mnemo == i_NOT ? 2 : 3));
  4224.         compile_note_modify(&map, eainfo, 0);
  4225.  
  4226.         if (insn_info[iip].dp->mnemo == i_NEG)
  4227.         cc_status = CC_Z_FROM_86Z | CC_C_FROM_86C | CC_V_FROM_86V | CC_N_FROM_86N | CC_X_FROM_86C;
  4228.         else {
  4229.         cc_status = CC_TEST_REG;
  4230.         cc_reg = eainfo[0].data_reg;
  4231.         cc_offset = 0;
  4232.         cc_size = eainfo[0].size;
  4233.         }
  4234.         break;
  4235.  
  4236.      case i_SWAP:
  4237.         /* No exits, no undo - this is always a Dreg; fetchea will get it in a reg
  4238.          * without offset */
  4239.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4240.                   insn_info[iip].dp->sreg, sz_long,
  4241.                   &realpc, current_addr,
  4242.                   eainfo, 0, EA_LOAD|EA_STORE, 1);
  4243.  
  4244.         compile_fetchea(&map, eainfo, 0, 1);
  4245.         compile_force_byteorder(&map, eainfo[0].data_reg, BO_NORMAL, 0);
  4246.  
  4247.         /* roll $16, srcreg */
  4248.         assemble(0xC1); assemble(0xC0 + eainfo[0].data_reg); assemble(16);
  4249.  
  4250.         /* @@@ un-shortcut */
  4251.         map.x86_dirty[eainfo[0].data_reg] = 1;
  4252.  
  4253.         cc_status = CC_TEST_REG;
  4254.         cc_reg = eainfo[0].data_reg;
  4255.         cc_offset = 0;
  4256.         cc_size = eainfo[0].size;        
  4257.         break;
  4258.         
  4259.      case i_LEA:
  4260.         /* No exits necessary here: never touches memory */
  4261.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4262.                   insn_info[iip].dp->sreg, 
  4263.                   insn_info[iip].dp->size, &realpc, current_addr,
  4264.                   eainfo, 0, 0, 1);
  4265.         eainfo[0].data_reg = eainfo[0].address_reg;
  4266.         eainfo[0].data_const_off = eainfo[0].addr_const_off;
  4267.         eainfo[0].address_reg = -1;
  4268.         compile_get_excl_lock(&map, eainfo + 0);
  4269.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4270.                   insn_info[iip].dp->dreg,
  4271.                   sz_long, &realpc, current_addr,
  4272.                   eainfo, 1, EA_STORE, 1);
  4273.         compile_storeea(&map, eainfo, 0, 1);
  4274.         cc_status = 0;
  4275.         break;
  4276.  
  4277.      case i_PEA:
  4278.         compile_prepare_undo(&map, Apdi, 7, &pub);
  4279.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4280.                   insn_info[iip].dp->sreg, 
  4281.                   insn_info[iip].dp->size, &realpc, current_addr,
  4282.                   eainfo, 0, 0, 1);
  4283.         eainfo[0].data_reg = eainfo[0].address_reg;
  4284.         eainfo[0].data_const_off = eainfo[0].addr_const_off;
  4285.         eainfo[0].address_reg = -1;
  4286.         compile_get_excl_lock(&map, eainfo + 0);
  4287.         compile_prepareea(&map, Apdi, 7, sz_long, &realpc, current_addr,
  4288.                   eainfo, 1, EA_STORE, 1);
  4289.  
  4290.         generate_possible_exit(&map, eainfo+1, iip, &pub);
  4291.         compile_storeea(&map, eainfo, 0, 1);
  4292.  
  4293.         cc_status = 0;
  4294.         break;
  4295.  
  4296.      case i_MVMEL:
  4297.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4298.                   insn_info[iip].dp->sreg, 
  4299.                   sz_word, &realpc, current_addr,
  4300.                   eainfo, 0, EA_LOAD, 1);
  4301.         sync_reg_cache(&map, 0);
  4302.         {
  4303.         /* Scratch 0 holds the registers while they are being moved
  4304.          * from/to memory. Scratch 1 points at regs.d. Scratch 2
  4305.          * points at the base addr in memory where to fetch data
  4306.          * from.
  4307.          */
  4308.         int scratch0, scratch1, scratch2;
  4309.         uae_u16 mask = eainfo[0].data_const_off;
  4310.         int bits = count_bits(mask);
  4311.         int size = insn_info[iip].dp->size == sz_long ? 4 : 2;
  4312.         int i;
  4313.         uae_u8 x86amode;
  4314.         uae_u32 current_offs = 0;
  4315.         
  4316.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  4317.         /* !!! Note current_addr + 2 here! */
  4318.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4319.                   insn_info[iip].dp->dreg,
  4320.                   insn_info[iip].dp->size, &realpc, current_addr + 2,
  4321.                   eainfo, 1, EA_LOAD, bits);
  4322.         
  4323.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  4324.  
  4325.         scratch0 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  4326.         lock_reg(&map, scratch0, 2);
  4327.         scratch1 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  4328.         lock_reg(&map, scratch1, 2);
  4329.         scratch2 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  4330.         lock_reg(&map, scratch2, 2);
  4331.         compile_force_byteorder(&map, eainfo[1].address_reg, BO_NORMAL, 0);
  4332.         
  4333.         compile_lea_reg_with_offset(scratch1, -2, (uae_u32)regs.regs);
  4334.         compile_lea_reg_with_offset(scratch2, eainfo[1].address_reg,
  4335.                         (uae_u32)(address_space + eainfo[1].addr_const_off));
  4336.  
  4337.         for (i = 0; i < 16; i++) {
  4338.             int r68k = i;
  4339.             int *cache68k = i < 8 ? map.dreg_map : map.areg_map;
  4340.             if (mask & 1 
  4341.             && (i < 8 
  4342.                 || insn_info[iip].dp->dmode != Aipi
  4343.                 || (r68k & 7) != insn_info[iip].dp->dreg)) {
  4344.             int tmpr = cache68k[r68k & 7];
  4345.             
  4346.             if (tmpr != -1) {
  4347.                 cache68k[r68k & 7] = -1;
  4348.                 map.x86_cache_reg[tmpr] = -1;
  4349.             }
  4350.             compile_move_reg_from_mem_regoffs(scratch0, scratch2,
  4351.                               current_offs, insn_info[iip].dp->size);
  4352.             if (size == 2) {
  4353.                 assemble(0x66); /* rolw $8,scratch0 */
  4354.                 assemble(0xC1);
  4355.                 assemble(0xC0 + scratch0);
  4356.                 assemble(8);
  4357.                 assemble(0x0F); assemble(0xBF); /* extend */
  4358.                 assemble(0xC0 + 9*scratch0);
  4359.             } else {
  4360.                 assemble(0x0F); /* bswapl scratch0 */
  4361.                 assemble(0xC8 + scratch0);
  4362.             }
  4363.             compile_move_reg_to_mem_regoffs(scratch1, (char *)(regs.regs + r68k) - (char *)regs.regs,
  4364.                             scratch0, sz_long);
  4365.             }
  4366.             if (mask & 1)
  4367.             current_offs += size;
  4368.             mask >>= 1;
  4369.         }
  4370.         }
  4371.         cc_status = 0;
  4372.         break;
  4373.  
  4374.      case i_MVMLE:
  4375.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4376.                   insn_info[iip].dp->sreg, 
  4377.                   sz_word, &realpc, current_addr,
  4378.                   eainfo, 0, EA_LOAD, 1);
  4379.         sync_reg_cache(&map, 0);
  4380.         {
  4381.         int scratch0,scratch1,scratch2;
  4382.         uae_u16 mask = eainfo[0].data_const_off;
  4383.         int bits = count_bits(mask);
  4384.         int size = insn_info[iip].dp->size == sz_long ? 4 : 2;
  4385.         int i;
  4386.         uae_u8 x86amode;
  4387.         uae_u32 current_offs = 0;
  4388.         int addrareg = -1;
  4389.         if (insn_info[iip].dp->dmode == Aind
  4390.             || insn_info[iip].dp->dmode == Apdi
  4391.             || insn_info[iip].dp->dmode == Aipi
  4392.             || insn_info[iip].dp->dmode == Ad16
  4393.             || insn_info[iip].dp->dmode == Ad8r)
  4394.         {
  4395.             addrareg = get_and_lock_68k_reg(&map, insn_info[iip].dp->dreg, 0, ADDRESS_X86_REGS, 1, 2);
  4396.             compile_force_byteorder(&map, addrareg, BO_NORMAL, 0);
  4397.         }
  4398.         if (insn_info[iip].dp->dmode == Apdi)
  4399.             mask = bitswap(mask);
  4400.         /* !!! Note current_addr + 2 here! */
  4401.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  4402.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4403.                   insn_info[iip].dp->dreg,
  4404.                   insn_info[iip].dp->size, &realpc, current_addr + 2,
  4405.                   eainfo, 1, EA_STORE, bits);
  4406.         
  4407.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  4408.  
  4409.         scratch0 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  4410.         lock_reg(&map, scratch0, 2);
  4411.         scratch1 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  4412.         lock_reg(&map, scratch1, 2);
  4413.         scratch2 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  4414.         lock_reg(&map, scratch2, 2);
  4415.  
  4416.         compile_force_byteorder(&map, eainfo[1].address_reg, BO_NORMAL, 0);
  4417.  
  4418.         compile_lea_reg_with_offset(scratch1, -2, (uae_u32)regs.regs);
  4419.         compile_lea_reg_with_offset(scratch2, eainfo[1].address_reg,
  4420.                         (uae_u32)(address_space + eainfo[1].addr_const_off));
  4421.  
  4422.         for (i = 0; i < 16; i++) {
  4423.             int r68k = i;
  4424.             if (mask & 1) {
  4425.             /* move from 68k reg */
  4426.             if (i < 8 || (i & 7) != insn_info[iip].dp->dreg || addrareg == -1) {
  4427.                 compile_move_reg_from_mem_regoffs(scratch0, scratch1, (char *)(regs.regs + r68k) - (char *)regs.regs,
  4428.                                   sz_long);
  4429.             } else {
  4430.                 assemble(0x8B); assemble(0xC0 + 8*scratch0 + addrareg);
  4431.             }
  4432.  
  4433.             if (size == 2) {
  4434.                 assemble(0x66); /* rolw $8,scratch0 */
  4435.                 assemble(0xC1);
  4436.                 assemble(0xC0 + scratch0); assemble(8);
  4437.             } else {
  4438.                 assemble(0x0F); /* bswapl scratch0 */
  4439.                 assemble(0xC8 + scratch0);
  4440.             }
  4441.             compile_move_reg_to_mem_regoffs(scratch2, current_offs,
  4442.                             scratch0, insn_info[iip].dp->size);
  4443.             }
  4444.             if (mask & 1)
  4445.             current_offs += size;
  4446.             mask >>= 1;
  4447.         }
  4448.         }
  4449.         cc_status = 0;
  4450.         break;
  4451. #if 1
  4452.      case i_BTST:
  4453.      case i_BSET:
  4454.      case i_BCLR:
  4455.      case i_BCHG:
  4456.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  4457.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  4458.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4459.                   insn_info[iip].dp->sreg, 
  4460.                   insn_info[iip].dp->size, &realpc, current_addr,
  4461.                   eainfo, 0, EA_LOAD, 1);
  4462.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4463.                   insn_info[iip].dp->dreg, 
  4464.                   insn_info[iip].dp->size, &realpc, current_addr,
  4465.                   eainfo, 1, 0, 1);
  4466.  
  4467.         generate_possible_exit(&map, eainfo, iip, &pub);
  4468.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  4469.  
  4470.         handle_bit_insns(&map, eainfo, 0, 1, insn_info[iip].dp->mnemo);
  4471.         break;
  4472.         
  4473.      case i_ASL: case i_ASR: case i_LSL: case i_LSR: 
  4474.      case i_ROL: case i_ROR: case i_ROXL:case i_ROXR:
  4475.         if (insn_info[iip].dp->smode == Dreg && do_rotshi) {
  4476.         handle_rotshi_variable(&map, iip, realpc, current_addr, &pub);
  4477.         break;
  4478.         }
  4479.         /* fall through */
  4480.      case i_ASLW: case i_ASRW: case i_LSLW: case i_LSRW: 
  4481.      case i_ROLW: case i_RORW: case i_ROXLW:case i_ROXRW:
  4482.         if (do_rotshi) {
  4483.         handle_rotshi(&map, iip, realpc, current_addr, &pub);
  4484.         break;
  4485.         }
  4486. #endif
  4487.      default:
  4488.         generate_exit(&map, insn_info[iip].address); cc_status = 0;
  4489.         break;
  4490.     }
  4491.     if (insn_info[iip].ccuser_follows)
  4492.         cc_status_for_bcc = compile_flush_cc_cache(&map, cc_status, 
  4493.                    insn_info[iip].flags_live_at_end,
  4494.                    1, insn_info[iip+1].flags_live_at_end,
  4495.                    insn_info[iip+1].dp->cc);
  4496.     else
  4497.         cc_status_for_bcc = compile_flush_cc_cache(&map, cc_status, 
  4498.                    insn_info[iip].flags_live_at_end,
  4499.                    0, 0, 0);
  4500.  
  4501.     if (iip == current_bb->last_iip) {
  4502.         current_bb++;
  4503.     }
  4504.     }
  4505.     if (compile_failure)
  4506.     goto oops;
  4507.  
  4508.     /* Compile all exits that we prepared earlier */
  4509.     finish_exits();
  4510.     if (compile_failure)
  4511.     goto oops;
  4512.     finish_condjumps(last_iip);
  4513.     {
  4514.     int needed_len = compile_here() - hb->compile_start;
  4515.     int allocsize = (needed_len + PAGE_SUBUNIT - 1) & ~(PAGE_SUBUNIT-1);
  4516.     uae_u32 allocmask;
  4517.     int allocbits;
  4518.     
  4519.     allocbits = (allocsize >> SUBUNIT_ORDER);
  4520.     allocmask = (1 << allocbits) - 1;
  4521.     while ((allocmask & hb->page_allocmask) != allocmask)
  4522.         allocmask <<= 1;
  4523.     if ((hb->page_allocmask & ~allocmask) != 0 && !quiet_compile)
  4524.         fprintf(stderr, "Gaining some bits: %08lx\n", hb->page_allocmask & ~allocmask);
  4525.     hb->cpage->allocmask &= ~hb->page_allocmask;
  4526.     hb->page_allocmask = allocmask;
  4527.     hb->cpage->allocmask |= allocmask;
  4528.     }
  4529.     return 0;
  4530.     
  4531.     oops:
  4532.     if (1 || !quiet_compile)
  4533.     fprintf(stderr, "Compile failed!\n");
  4534.     hb->cpage->allocmask &= ~hb->page_allocmask;
  4535.     hb->cpage = NULL;
  4536.     hb->untranslatable = 1;
  4537.     {
  4538.     struct hash_entry *h = hb->he_first;
  4539.     
  4540.     do {
  4541.         h->execute = NULL;
  4542.         h = h->next_same_block;
  4543.     } while (h != hb->he_first);
  4544.     }
  4545.     return 1;
  4546. }
  4547.  
  4548. void compiler_init(void)
  4549. {
  4550.     code_init();
  4551.     hash_init();
  4552.     jsr_stack_init();
  4553. }
  4554.  
  4555. /*
  4556.  * Why do compilers always have to be so complicated? And I thought GCC was
  4557.  * a mess...
  4558.  */
  4559.  
  4560. #endif /* USE_COMPILER */
  4561.